Pomoc - Szukaj - Użytkownicy - Kalendarz
Pełna wersja: [Postgres] pobieranie dzielnicy zamieszkania i liczby pacjentów, którzy mieli już wykananą usługę
Forum PHP.pl > Forum > Bazy danych
kaem
Witam, mam takie 3 tabele (wersja skrócona):
patients: idpatients, iddistrict
district(dzielnica): iddistrict, name
teeth_services(usługa): idteeth_services, idpatient, service_date

Chce zrobić podsumowanie, ilu z poszczególnych dzielnic jest pacjentów w bazie, którzy mieli już wykonaną jakaś usługę (czyli taką jakby mapę pacjentów).
Narazie doszedłem tylko jak pobrać ilość pacjentów w poszczególnych dzielnicach:
  1. SELECT district.name,patients.iddistrict, count(*) AS ile
  2. FROM district
  3. LEFT JOIN patients
  4. ON district.iddistrict = patients.iddistrict
  5.  
  6. GROUP BY district.name, patients.iddistrict
  7. ORDER BY district.name ASC

Też chyba to zapytanie nie bardzo bo w wyniku mam:
name | iddistrict | ile
Rury | 2 |4
Felin | null |1
i tam gdzie mam w iddistrict null, w php jako ile musze wstawić 0 żeby to miało sens.

A teraz próbując zmienić to zapytanie aby pobierało pacjentów, którzy mieli wykonaną usługę wykombinowałem coś takiego (ŹLE):
  1. SELECT district.name,patients.iddistrict, count(*) AS ile
  2. FROM district
  3. LEFT JOIN patients
  4. ON district.iddistrict = patients.iddistrict
  5. LEFT JOIN teeth_services
  6. ON teeth_services.idpatient = patients.idpatients
  7. GROUP BY district.name, patients.iddistrict
  8. ORDER BY district.name ASC


ALE nie działa poprawnie, ponieważ np. jak mam 2 pacjentów z dzielnicy, np. Rury, jeden miał w sumie wykonanych usług 5, a drugi 1 to w wyniku w kolumnie 'ile' zwraca mi 6 a ma zwrócić 2. Proszę o pomoc w poprawieniu tego.

Pozdrawiam.
mortus
Wartość iddistrict raczej nie może być równa null, no chyba, że któryś pacjent nie mieszka w żadnej z dzielnic. Jak to jest?

Problem nie jest taki prosty z kilku względów (m. in. dlatego, że COUNT działa trochę inaczej niżbyśmy chcieli). Obawiam się, że bez podzapytań się nie obejdzie. Wymyśliłem coś takiego:
  1. SELECT d.iddistrict, d.name, districts_patients.patients_number
  2. FROM district d
  3. LEFT JOIN (SELECT p.iddistrict, COUNT(*) AS patients_number
  4. FROM patients p
  5. INNER JOIN (SELECT DISTINCT ts.idpatient
  6. FROM teeth_services ts) AS patients_services
  7. ON patients_services.idpatient = p.idpatients
  8. GROUP BY p.iddistrict) AS districts_patients
  9. ON districts_patients.iddistrict = d.iddistrict;

Jak to działa? Otóż łączymy tabelę district z tymczasową tabelą, w której podliczono liczbę pacjentów przypadających na każdą dzielnicę. Tabela ta nazywa się districts_patients i powstaje ona z połączenia tabeli patients z drugą tabelą tymczasową patients_services, w której to umieszczamy bez powtórzeń identyfikatory pacjentów, którzy skorzystali z jakiejś usługi.
Pytania. Czy jest to rozwiązanie optymalne? Czy w przypadku olbrzymiej ilości danych nie lepiej będzie rozwiązać problem po stronie aplikacji, wykonując nie jedno, ale kilka różnych zapytań?
kaem
Dzięki, zaraz przetestuje i napiszę co wyszło.
A czy optymalne hmmm, w sumie w tej aplikacji nie ma jakiegoś dużego ciśnienia aby to działało b. szybko ponieważ bardzo rzadko będzie to zapytanie wykorzystywane, a jeśli już to prawdopodobnie tylko raz podczas jednej 'sesji' z aplikacją.
Co do pola iddistrict - może być ono puste, np. dla pacjentów spoza granic administracyjnych miasta, a tacy też się zdarzają.

EDIT://
@mortus, działa jak należy, dzięki serdeczne smile.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.