Pomoc - Szukaj - Użytkownicy - Kalendarz
Pełna wersja: Jak napisać zapytanie
Forum PHP.pl > Forum > Bazy danych > MySQL
SamoChwała
Nie wiedziałem za bardzo jaki dać tytuł, a chodzi mi o zapytanie, które spełniło by następujący warunek.

Zakładając, że prowadze księgarnie i mam w Tab1 skatalogowane ksiązki. W Tab2 rejestruję datę wyporzyczenia. Teraz chcę otrzymać w wyniku wszystkie książki które nie zostały wpożyczone w zadanym okresie czasu.

Kombinowałem tak (w tym przykładzie są akurat wstawione daty, normalnie są zczytywane z pola "input".

  1. SELECT
  2. `Tab1`.`idKsiazki`,
  3. `Tab1`.`tytul`,
  4. `Tab1`.`dzial`,
  5. `Tab2`.`data`
  6. FROM `Tab1` LEFT OUTER JOIN `Tab2` ON (`Tab1`.`idKsiazki` = `Tab2`.`idKsiazki`)
  7. WHERE (`Tab1`.`dzial` = 8) AND (`Tab2`.`data` BETWEEN '2004-01-01' AND '2004-03-15')


Próbowałem też bez "LEFT OUTER JOIN " na samych warunkach "Tab1.idKsiazki<>Tab2.idKsiazki" i też lipa.

Może ktoś pomóc?
cim
  1. SELECT Tab1.idksiazki, Tab1.tytul, Tab1.dzial, Tab2.DATA FROM Tab1, Tab2 WHERE (Tab1.idKsiazki = Tab2.idKsiazki) AND (Tab1.dzial = 8) AND (Tab2.DATA BETWEEN '2004-01-01' AND '2004-03-15')

:?:
popbart
To powinno wyświetlić wszystkie książki nie wypożyczone
  1. SELECT Tab1.idksiazki, Tab1.tytul, Tab1.dzial
  2. FROM Tab1 LEFT JOIN Tab2 ON Tab1.idksiazki=Tab2.idksiazki
  3. WHERE Tab2.idKsiazki IS NULL
  4. GROUP BY Tab1.idksiazki
  5. ORDER BY Tab1.tytul

cool.gif
SamoChwała
  1. SELECT Tab1.idksiazki, Tab1.tytul, Tab1.dzial, Tab2.DATA FROM Tab1, Tab2 WHERE (Tab1.idKsiazki = Tab2.idKsiazki) AND (Tab1.dzial = 8) AND (Tab2.DATA BETWEEN '2004-01-01' AND '2004-03-15')

Takie zapytanie nie wyświetla żadnego rekordu, jusz to przerabiałem w róznych wariantach i z różnymi warunkami.

  1. SELECT Tab1.idksiazki, Tab1.tytul, Tab1.dzial
  2. FROM Tab1 LEFT JOIN Tab2 ON Tab1.idksiazki=Tab2.idksiazki
  3. WHERE Tab2.idKsiazki IS NULL
  4. GROUP BY Tab1.idksiazki
  5. ORDER BY Tab1.tytul



To wszystko jest OK! jeśli mają być pokazane wszystkie książki które jeszcze nie zostały wypożyczone. Do takich samych wyników doszedłem chociaż odrobinę inaczej skonstruowane było(y) pytania.

Problemem jest wylistowanie książek, które nie były wypożyczone np. w 1 kwartale tego roku. Od konkretnej daty do konkretnej daty.
rogrog
  1. ... HAVING DATA BETWEEN '2004-01-01' AND '2004-03-15'
SamoChwała
To też już testowałem, efekt taki sam. Wyświetla ZERO rekordów.

Coś czytałem o tabelach wirtualnych (tymczasowych) tylko nie jestem pewien czy to dotyczyło akurat MySQL. Wtedy chyba było by łatwo zastosować to 1 zapytanie do wirtualnej tabeli w której były by tylko rekordy z zadanego okresu.

Dobrze kombinuje? Czy może jest inne rozwiązanie?
peyn
Hmm, zdaje mi sie ze jednym zapytaniem tego w mySQLu nie da sie zrobic jako ze nie ma tutaj zapytan zagniezdzonych. Gdyby byly zrobilbym to tak:

  1. SELECT a.* FROM Tab1 a WHERE a.idksiazki NOT IN (SELECT b.idksiazki FROM Tab2 b WHERE (b.DATA BETWEEN '2004-01-01' AND '2004-03-15') ORDER BY b.DATA) ORDER BY a.idksiazki;


No ale skoro nie ma to zakladajac ze robisz to w php zrobilbym to tak :-)

  1. <?php
  2.  
  3. $z = &#092;"SELECT idksiazki FROM Tab2 WHERE (data BETWEEN '2004-01-01' AND '2004-03-15') ORDER BY data\";
  4. $w = mysql_query($z);
  5. while($r = mysql_fetch_array($w))
  6. {
  7. if($id=='')
  8. {
  9.  $id=$r['idksiazki'];
  10. }
  11. else
  12. {
  13. $id.=','.$r['idksiazki'];
  14. };
  15. }
  16.  
  17. //a teraz juz tylko pobranie ksiazek i ich wyswietlenie
  18. $z = &#092;"SELECT idksiazki FROM Tab1 WHERE idksiazki NOT IN (\".$id.\")\";
  19. $w = mysql_query($z);
  20. while($r = mysql_fetch_array($w))
  21.  
  22.  
  23. ?>


Tak bym to zrobil ale jak jest jakis prostrzy sposob to dajcie znac.
SamoChwała
peyn jesteś wielki!!! Dzięki w imieniu kolegi - TO DZIAŁA!

Fak, MySQL ma jednak kilka wad w odróżnieniu od SQL. M.in. brak możliwości konstruowania podzapytań, a to boli. Podobnie jak brak UNION.
Chodzą słuchy, że od wersji 5 te niedogodności mają być usunięte. Przynajmniej UNION ma być (już nawet w wersji beta jest - czytałem).

Rozwiązałem ten problem podobnie, ale tworząc jako pierwszą tabelę tymczasową:
  1. CREATE TEMPORARY TABLE Tab2_kopia
  2. SELECT idKsiazki, Tytul, dataWyp
  3. FROM Tab2 WHERE DATA BETWEEN '2004-01-01' AND '2004-03-15'


Działa również prawie poprawnie. Prawie dlatego, że nie pozwala wybrać ponownego zakresu dat (zczytywane z pol INPUT). Po pierwszym odpaleniu jest OK, a przy ponownym wywala błąd. Muszę jeszcze posiedzieć nad zwolnieniem pamięci. Standardowe zamknięcie tabeli nie pomaga (lub z moim kompem tzn. serwerm coś nie tak).

Reasumując Twoje rozwiązanie jest znacznie szybsze i nie obciąża zbędnie pamięci.

Jeszcze raz dziękuje.
peyn
Co do UNION w mySQLu to jest pewien trick (nie do konca go pamietam a wale z glowy wiec moge walnac jakiegos byczka)

Zalozmy ze chcemy polaczyc 2 tabele (tab1, tab2). Tworzymy do tego celu trzecia tabele - powiedzmy tmp. W tej trzeciel tabeli tworzymy 1 kolumne i do niej wpisujemy 2 rekordy (np: 1,2) Gdybysmy chcieli polaczyc 3 tabele to wstawiamy 3 rekordy, 4 to 4, itd.

Teraz wystarczy juz tylko zrobic takie zapytanie zeby polaczyc JOINem tab1 z tmp na podstawie pola gdzie wartosc=1 a tab2 z tmp na podstawie pola gdzie wartosc=2.

Wtedy otrzymujemy mniej wiecej cos takiego

--------------------------------
1 | Wartosc z Tab1
2 | Wartosc z Tab2
2 | Wartosc z Tab2
1 | Wartosc z Tab1

Czyli mamy jakby takiego UNIONa

biggrin.gif
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.