Pomoc - Szukaj - Użytkownicy - Kalendarz
Pełna wersja: [MySQL][PHP] Optymalizacja SQL statement
Forum PHP.pl > Forum > Przedszkole
adek-
Cześć Wam, mam mały problem, tzn wszystko co pokazuję działa, ale chcę uzyskać jeszcze więcej za pomocą jednego zapytania niż mam do tej pory... proszę nakierujcie mnie, na pewne schematy którymi powinienem się kierować w takich przypadkach w przyszłości.

Fakty: są trzy firmy, każda z nich ma około 2,3 lokale i to jest skrypt dodający umowy tych lokali przypisanych do danej firmy i informujący mnie kiedy się kończy umowa najmu, jaka jest kwota najmu i jaka jest kaucja. Do każdego lokalu można dodać więcej niż jedną umowę, ale brana jest pod uwagę tylko ta ostatnio dodana (najbardziej aktualna) w zapytaniu zrobiłem inner joina z MAX(timestamp) i zapytanie listuje mi ostatnio dodaną umowę na każdy z punktów. Wszystko ok, więc może trochę kodu... zapytanie do bazy i pętla która mi sumuje dwie wartości, czynsz i kaucja:
  1. $sql = "SELECT kr.*, ks.id_spolki, ks.skrot
  2. from lokal_rent kr
  3. inner join (
  4. select
  5. id_lokal, max(timestamp) as latest
  6. from lokal_rent
  7. group by id_lokal
  8. ) kr2
  9. on kr.timestamp = kr2.latest and kr.id_lokal = kr2.id_lokal
  10. left join spolki ks on kr.id_spolki = ks.id_spolki
  11. order by kr.id_lokal desc";

  1. $result = mysqli_query($link, $sql) or die(mysqli_error($link));
  2. $temp = array();
  3. $rent_prize = 0;
  4. $deposit_prize = 0;
  5. while ($row = mysqli_fetch_array($result)) {
  6. $suma[] = array(
  7. 'id' => $row['id'],
  8. 'id_lokal' => $row['id_lokal'],
  9. 'skrot_firmy' => $row['skrot_firmy'],
  10. 'rent_prize' => $row['rent_prize'],
  11. 'deposit_prize' => $row['deposit_prize']);
  12. //dodawanie zmiennych w rzędzie
  13. $rent_prize += round((float) $row['rent_prize'], 2);
  14. $deposit_prize += round((float) $row['deposit_prize'], 2);
  15. }

wyrzuca mi dane poprawne, wszystko się przelicza jak powinno, ale teraz moje pytania, jako, że nie mogłem sobie z tymi kwestiami poradzić, tzn mogę, ale używam kilku osobnych zapytań, a chcę wiedzieć, czy to jedno tylko bardziej rozbudowane będzie mogło obsłużyć to wszystko o czym mówię poniżej?

1. Czy da się w jakiś łatwy sposób poza sumowaniem aktywnych umów, co mam zrobione powyżej w php, zrobić w tym zapytaniu dodatkowo sumowanie wg. firm? Gdy dawałem group by id_spolki przed order by, to zapytanie od razu zmieniało swoje wyniki i nie spełniało założeń, a usunąć ani zmienić order by id_lokal na coś innego nie mogę, bo wtedy będzie mi wyświetlać wadliwie wyniki po max(timestamp) czyli tych najnowszych umowach. Zacząłem już robić pole active=0/1 i dodanie każdej następnej umowy w założeniu będzie dezaktywowało poprzednią active=0 zostawiając ostatnią aktywną=1, wtedy pozbędę się problemu z max(ts) i będę mógł użyć WHERE active=1. W dobrym kierunku idę?

2. Gdy chciałem sumować w samym zapytaniu sql rent_prize i deposit_prize poprzez SUM() zapytanie zmieniało całkowicie swój wynik, nie ważne czy było to w zapytaniu głównym, czy podzapytaniu (inner join)! Stąd ten temp array. Czy faktycznie nie dałoby się też tego zrobić unikając niepotrzebnych tablic w php?

3. Chciałem też nieskutecznie zrobić liczenie ilości umów dodanych w danym lokalu i wyświetlić ich liczbę obok nazwy lokalu, ale jedyne na co moja wiedza mi pozwalała to w tym zapytaniu zliczyć ilość wierszy jakie wyrzuca zapytanie - $num_rows = mysqli_num_rows($result);, czyli nie to o co mi chodziło.

3. Ostatni pomysł, trochę czasochłonny, ale może tutaj próbować zrobić temp_table, wrzucać wszystkie potrzebne dane, sumować co chce i jak chce itd? Ale de facto mija się to z moim pierwszym założeniem - zrobić jak najwięcej można w jednym zapytaniu, bo równie dobrze mogę to wszystko zrobić zamiast temp_table to poprzez kilka odrębnych zapytań! W sumie to nawet nie wiem która opcja jest bardziej poprawna i uznawana, więcej zapytań i tablic array, czy tworzenie temp_table za pomocą PHP i odczytywanie z nich (tablica działa do czasu wylogowania użytkownika, więc zapewne mniej obciąża system, niż ciągłe liczenie w PHP i zadawanie ciągle tych samych zapytań).

Proszę o nakierowanie. Jeśli będzie potrzeba coś udostępnić z dodatkowym kodem to z chęcią! Chociaż sprawne zapytanie jest, ale wiedzy brak! biggrin.gif
Damonsson
Ad 1+2. Sumowania dla firm, nie połączysz z wyświetlaniem dla lokali o ile dobrze rozumiem założenie. Przynajmniej nie jakoś prosto i po ludzku w MySQL, mógłbyś kombinować żeby dla każdej firmy wyświetlać sumę zadłużenia w każdym wierszu dla lokalu jak masz rzeczywiście tylko 3 i nie planujesz więcej, ale po co to komu. Licz to sobie w osobnym zapytaniu, nie ma z tym problemu, to nie są wbrew pozorom powiązane ze sobą dane.

Ad 3.
To powinno Ci załatwić problem:
  1. SELECT kr.*, ks.id_spolki, ks.skrot, kr2.ilosc_umow_dla_lokalu FROM lokal_rent kr
  2. LEFT JOIN spolki ks ON kr.id_spolki = ks.id_spolki
  3. JOIN (SELECT id_spolki, COUNT(*) AS ilosc_umow_dla_lokalu, max(timestamp) AS latest FROM lokal_rent GROUP BY id_spolki) kr2
  4. ON kr2.id_spolki= kr.id_spolki AND kr.timestamp= kr2.latest
  5. ORDER BY kr.id_spolki DESC;
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.