Pomoc - Szukaj - Użytkownicy - Kalendarz
Pełna wersja: [PHP][MySQL] Pętla, optymalizacja zapytania
Forum PHP.pl > Forum > Przedszkole
desavil
Witajcie, mam taki skrypt:

  1. $start = 100;
  2. $end = 199;
  3.  
  4.  
  5. for($lp=$start;$lp<=$end;++$lp){
  6. if($lp%2 == 0){
  7. $zap=mysql_query("SELECT * FROM ids WHERE number='$lp'");
  8. if(mysql_num_rows($zap) <= 0){
  9. $id = ++$id;
  10. if($id == 1){ echo $lp."\n"; }
  11. }
  12. }
  13. }


Da się to zapytanie jakoś zoptymalizować, aby nie wysyłać dla każdego numeru osobnego zapytania tylko za jednym razem np?
kudlatypawelek
SELECT * FROM ids WHERE number IN ('dane liczbowe'). W 'dane liczbowe' musisz wstawić odpowiedni "string" z numerami, dla których chcesz pobierać rekordy z bazy. Ten string przygotuj sobie rzeczywiście w pętli używając phpa, a potem przekaż do zapytania.
skowron-line
  1. SELECT * FROM ids WHERE number >= 100 AND number <= 199 AND number % 2 != 0
zobacz coś takiego.
desavil
Not work sad.gif

  1. $start = 100;
  2. $end = 199;
  3. $sql = $pdo -> query('SELECT * FROM `ids` WHERE `number` >= '.$start.' AND `number` <= '.$end.' AND `number` % 2 != 0');
  4. while($sql_row = $sql-> fetch()){
  5. $id = ++$id;
  6. if($id == 1){ echo $lp."\n"; }
  7. }
skowron-line
Cytat(desavil @ 16.08.2011, 13:33:20 ) *
Not work sad.gif


Gościu bo miękną mi kolana jak coś takiego czytam. Co nie działa questionmark.gif Zapytanie się nie wykonuje czy zwraca zły wynik questionmark.gif Czy jeszcze coś innego questionmark.gif Wklej to co podałem do PMA
desavil
Nie działa = nie działa smile.gif

Ani PhpMyAdmin nic nie zwraca, ani skrypt.
luckyps
operator_between
desavil
Wolałbym gotowca jeżeli to w miarę możliwe.
luckyps
  1. query = 'SELECT * FROM `ids` WHERE `number` between '.$start.' and '.$end.' AND `number` % 2 != 0';
desavil
Nadal nie działa, ani w skrypcie ani PMA nic nie zwraca.
Może opiszę działanie tego kodu, może źle zrozumieliście o co w nim chodzi.

Skrypt ma wyświetlać liczby co dwa od podanego zakresu. I sprawdzać, czy w bazie danych ta liczba istnieje, czy też nie.
Jeżeli istnieje liczba ta nie jest wyświetlana.
luckyps
To w takim razie pokaz Nam wycinek danych z tabeli gdzie kolumna number jest pomiedzy 100 a 199...
desavil
Ehhh :/
Pętla generuje liczny co dwa:
2
4
6
8
10

Każdą z tych liczb sprawdzam w bazie danych, czy istnieje jeżeli istnieje to nie jest wyświetlana, czyli np. w bazie danych są liczby 4, 10 to skrypt wyświetli:
2
6
8

Chodzi o to, że w pętli do każdej liczby jest generowanie zapytanie, o sprawdzenie tej liczby.
Jeżeli dam zakres liczb do sprawdzenia np. od 100000 do 800000, będzie generowana bardzo spora liczba zapytań do bazy.
I chodzi mi o jakieś rozwiązanie tego, aby nie generować tylu zapytań. Może da się jakoś to przerobić i pobrać za pierwszym razem wszystkie numery ID, a później porównywać i ew. wyświetlać daną liczbę lub też nie.
luckyps
Wykonujac takie zapytanie :
  1. query = 'SELECT `number` FROM `ids` WHERE `number` between '.$start.' and '.$end.' AND `number` % 2 = 0';

otrzymasz wszystkie liczby parzyste, z przedzialu pomiedzy $start i $stop, które znajdują się w tabeli `ids`.
Wystarczy teraz zrobic petle w php od $start do $end,
  1. for($i = $start; $i < ($end); $i++)
  2. {
  3. if ($i % 2 = 0) {
  4. ...
  5. }
  6. }

i sprawdzic czy dla danego $i jest juz taka liczba w tabeli, jesli nie to rob1() jesli tak to rob2() .
desavil
Wywołując zapytanie, nie trzeba sprawdzać, czy są parzyste. Wystarczy mi zapytanie.
'SELECT * FROM ids'

I chodzi mi o to jak zrobić później to porównanie.
luckyps
Cytat(desavil @ 16.08.2011, 17:12:20 ) *
Wystarczy mi zapytanie.
SELECT * FROM ids WHERE number='numery_z_petli'.


No wlasnie nie wystarczy Ci to zapytanie... bo to sprawdzi tylko jeden numer...
desavil
A jak by zrobić coś takiego:

  1. for($lp=$start;$lp<=$end;++$lp){
  2. if($lp%2 == 0){ $lp_view[$lp] = $lp; } //tutaj poprawić bo chyba jest źle
  3. }
  4. $pdo = con();
  5. $sql_dane = $pdo -> query('SELECT ids FROM `number');
  6. while($sql_dane_row = $sql_dane -> fetch()){
  7. // tutaj porównanie z wyświetlonymi, jeżeli znajdzie w bazie, nie wyświetla, jeżeli nie znajdzie, wyświetla.
  8. }


Pomoże ktoś snitch.gif

Napisał by ktoś gotowca?
Bardzo proszę, mocno mi jest to potrzebne, a nie umiem sam tego napisać.

Umie ktoś napisać/przerobić mi ten skrypt?
phpion
Proszę bardzo:
  1. SELECT row FROM (SELECT @row := @row + 1 AS row FROM
  2. (SELECT 0 UNION ALL SELECT 1 UNION ALL SELECT 3 UNION ALL SELECT 4 UNION ALL SELECT 5 UNION ALL SELECT 6 UNION ALL SELECT 6 UNION ALL SELECT 7 UNION ALL SELECT 8 UNION ALL SELECT 9) t1,
  3. (SELECT 0 UNION ALL SELECT 1 UNION ALL SELECT 3 UNION ALL SELECT 4 UNION ALL SELECT 5 UNION ALL SELECT 6 UNION ALL SELECT 6 UNION ALL SELECT 7 UNION ALL SELECT 8 UNION ALL SELECT 9) t2,
  4. (SELECT 0 UNION ALL SELECT 1 UNION ALL SELECT 3 UNION ALL SELECT 4 UNION ALL SELECT 5 UNION ALL SELECT 6 UNION ALL SELECT 6 UNION ALL SELECT 7 UNION ALL SELECT 8 UNION ALL SELECT 9) t3,
  5. (SELECT 0 UNION ALL SELECT 1 UNION ALL SELECT 3 UNION ALL SELECT 4 UNION ALL SELECT 5 UNION ALL SELECT 6 UNION ALL SELECT 6 UNION ALL SELECT 7 UNION ALL SELECT 8 UNION ALL SELECT 9) t4,
  6. (SELECT @row:=0) row) seq
  7. LEFT JOIN news ON (news.id = row)
  8. WHERE
  9. row BETWEEN 1 AND 20
  10. AND news.id IS NULL;

Jednym zapytaniem zwracasz to, co Cię interesuje. U mnie testowałem na tabeli news i kolumnie id (news.id) - zmień to pod siebie. Ok, jak to działa. Te linie z t1, t2, t3, t4 generują Ci sekwencję liczb od 1 do 1000. Dodając analogiczną linię t5 otrzymasz liczby od 1 do 10000. Następnie robisz złączenie z tabelą, o którą Ci chodzi (news) z warunkiem news.id = row czyli id newsa musi odpowiadać aktualnej wartości row. Dalej: interesują nas tylko wartości row z przedziału od 1 do 20 (wstaw swój zakres) oraz takie dane, gdzie news.id jest NULLem, czyli po prostu nie ma rekordu w tabeli newsów.

PS: ten warunek przeskoku co 2 wartości dorób sobie sam smile.gif
desavil
To jest chyba najgorsze rozwiązanie jakie może być.
Dlaczego nie chce nikt dokończyć tego kodu, który ja zaproponowałem.

Jak ja będę generował liczby od 1 do 1000000 to chyba nie będę do zapytania dodawał tych całych UNION itp...
phpion
Cytat(desavil @ 20.08.2011, 16:38:48 ) *
To jest chyba najgorsze rozwiązanie jakie może być.

Chyba się mylisz.

Cytat(desavil @ 20.08.2011, 16:38:48 ) *
Jak ja będę generował liczby od 1 do 1000000 to chyba nie będę do zapytania dodawał tych całych UNION itp...

No tak, lepiej wysłać te 1000000 zapytań do bazy danych. Gratulacje pomysłowości. A co do UNION: je możesz wygenerować automatycznie pętlą...
desavil
Dlaczego?

Przecież chodzi mi cały czas o to, aby pobrać WSZYSTKIE rekordy z bazy o SELECT np. id i umieścić je w tablicy.
Później wygenerować liczby i każdą z tych liczb porównywać z tablicą.

@edit
Podpowie ktoś jeszcze jak wyświetlić to co dwa/parzyste?
Wiem, że w zapytaniu muszę dodać gdzieś %2, ale w którym miejscu i czy na pewno to hmm. Próbowałem różnie i nie działało.
phpion
Cytat(desavil @ 20.08.2011, 17:26:32 ) *
@edit
Podpowie ktoś jeszcze jak wyświetlić to co dwa/parzyste?
Wiem, że w zapytaniu muszę dodać gdzieś %2, ale w którym miejscu i czy na pewno to hmm. Próbowałem różnie i nie działało.

Pokombinuj z tym fragmentem:
Kod
@row := @row + 1

smile.gif
kefirek
  1. $start = 100;
  2. $end = 199;
  3.  
  4. $start = ($start % 2 == 0 ? $start : $start + 1);
  5.  
  6. $numbers = range($start, $end, 2);
  7.  
  8. $comma_separated = implode(",", $numbers);
  9.  
  10. $result = mysql_query("SELECT number FROM ids WHERE number IN (".$comma_separated.")");
  11. if(mysql_num_rows($result) > 0){
  12. while ($data = mysql_fetch_assoc($result)){
  13.  
  14. $array_num[]=$data['number'];
  15.  
  16. }
  17. }
  18.  
  19.  
  20. for ($i = 0;isset($numbers[$i]);++$i){
  21.  
  22. if (!in_array($numbers[$i], $array_num)){
  23. echo $numbers[$i].'</br>';
  24. }
  25.  
  26. }
desavil
Dzięki, i o to mi chodziło :]

Tylko coś to nie działa, bo liczby istnieją w bazie, a i tak są wyświetlane.
Hmm sad.gif
kefirek
Daj
  1. echo '<pre>';
  2. print_r($array_num);
  3. echo '</pre>';


I powiedz czy coś wywietla jeśli nie znaczy ze nie pobiera liczb z bazy

Zobacz czy zmiana
  1. $result = mysql_query("SELECT number FROM ids WHERE number IN (".$comma_separated.")");


Na
  1. $result = mysql_query("SELECT number FROM ids WHERE number IN ($comma_separated)");


Pomoże
desavil
Działa, mój błąd w $array_num[]=$data['nazwa'] zapomniałem zmienić tongue.gif

Z góry jeszcze raz Wielkie dzięki :]

Jest pewien błąd. Jak w bazie nie ma dodanego żadnego rekordu, lub też wszystkie liczby są inne w bazie niż z podanego zakresu, np. jeżeli podaję zakres od 100-200, a w bazie mam rekordy o ID 2500 to pojawia się taki błąd:

Cytat
Warning: in_array() [function.in-array]: Wrong datatype for second argument

Na linii podanej w błędzie jest to:
  1. if (!in_array($numbers[$i], $array_num)){
melkorm
Zainicjuj tą zmienną przed skryptem jako pustą tablicę.
desavil
Nic :/
Ani: $numbers[] = ''; nie pomogło ani $array_num = '';
Smertius
  1. $array_num = array();
desavil
I poleciały plusikowe biggrin.gif

melkorm, za pomysł.
Smertius, za wykonanie.

Dzięki.
To jest wersja lo-fi głównej zawartości. Aby zobaczyć pełną wersję z większą zawartością, obrazkami i formatowaniem proszę kliknij tutaj.
Invision Power Board © 2001-2025 Invision Power Services, Inc.