Witaj Gościu! ( Zaloguj | Rejestruj )

Forum PHP.pl

 
Reply to this topicStart new topic
> Znajdowanie rekordów z pojedynczą relacją w innej tabeli, Join + On + Group By + Having
Grzeniu
post 26.10.2017, 10:54:47
Post #1





Grupa: Zarejestrowani
Postów: 5
Pomógł: 0
Dołączył: 24.10.2017

Ostrzeżenie: (0%)
-----


Cześć,

Mam obecnie taką strukturę tabeli:
tabela vtiger_activity - gdzie są wpisy dotyczące zdarzeń mające m.in. swoje id - vtiger_activity.activityid oraz status - vtiger_activity.eventstatus
tabela vtiger_crmentityrel - gdzie zapisane sa relacje między różnymi typami rekordów, w tym przypadku między ID klientów (crmid) oraz ID zdarzeń (relcrmid), które są przypisane do danych klientów. Pojedynczy klient może mieć przypisanych wiele zdarzeń.
Tutaj bardziej obrazowo:


Ja chciałbym wybrać z tabeli vtiger_activity tylko te rekordy zdarzeń, które są jedynymi przypisanymi do swoich klientów. Przykładowo: klient A ma zdarzenia Z1, Z2, Z3, klient B ma tylko Z4, klient C ma tylko Z5. Czyli ja chcę wybrać tylko Z4, Z5.

Próbowałem wykonać to za pomocą group by i having count(*) = 1, jak poniżej, lecz to nadal zwraca takie zdarzenia, które przypisane są do klientów z kilkoma przypisanymi zdarzeniami. Nie potrafię obmyślić prawidłowej logiki tego zapytania, więc sugestie bardzo mile widziane.

  1. SELECT
  2. vtiger_crmentityrel.crmid AS id_klienta,
  3. vtiger_crmentityrel.relcrmid AS id_zdarzenia,
  4. vtiger_activity.subject,
  5. vtiger_activity.eventstatus
  6. FROM vtiger_activity
  7. JOIN panel.vtiger_crmentityrel
  8. ON vtiger_crmentityrel.relcrmid = vtiger_activity.activityid
  9. GROUP BY vtiger_crmentityrel.crmid
  10. HAVING count(*) = 1


Ten post edytował Grzeniu 26.10.2017, 11:02:03
Go to the top of the page
+Quote Post
sabat24
post 26.10.2017, 13:46:12
Post #2





Grupa: Zarejestrowani
Postów: 175
Pomógł: 26
Dołączył: 13.09.2007
Skąd: Gdańsk

Ostrzeżenie: (0%)
-----


Nie mam teraz chwili, by przekładać Twoje nazwy kolumn, ale ja używam poniższej mechaniki, by osiągnąć to, co Ty chcesz.

Do głównego SELECTa (pomiń warunki i JOINy związane z tym, że liczba powiązań musi być równa 1) dodaj coś takiego:

  1. WHERE EXISTS (
  2. SELECT a2r.room_id FROM accessories_to_rooms a2r WHERE a2r.room_id = r.r_id AND a2r.company_id = c.c_id GROUP BY a2r.room_id HAVING COUNT(a2r.room_id) = 1)


U mnie a2r to jest tabela z relacjami n:n (u Ciebie zdarzenia) a r to jest ta Twoja kliencka.
To zwraca tylko te rekordy z tabeli klienckiej, które mają dokładnie X relacji.

Go to the top of the page
+Quote Post
Grzeniu
post 30.10.2017, 11:34:38
Post #3





Grupa: Zarejestrowani
Postów: 5
Pomógł: 0
Dołączył: 24.10.2017

Ostrzeżenie: (0%)
-----


Cytat(sabat24 @ 26.10.2017, 14:46:12 ) *
  1. WHERE EXISTS (
  2. SELECT a2r.room_id FROM accessories_to_rooms a2r WHERE a2r.room_id = r.r_id AND a2r.company_id = c.c_id GROUP BY a2r.room_id HAVING COUNT(a2r.room_id) = 1)


U mnie a2r to jest tabela z relacjami n:n (u Ciebie zdarzenia) a r to jest ta Twoja kliencka.
To zwraca tylko te rekordy z tabeli klienckiej, które mają dokładnie X relacji.


Starałem się poukładać swoje zapytanie, ale coś ewidentnie robię źle. Puszczam zapytanie przez phpAdmina i wykonuje się ono chyba w nieskończoność - aż serwer zrywa połączenie.

Poniżej kod. W twoim poście nie rozumiałem
FROM accessories_to_rooms a2r WHERE
Czym jest w moim przypadku twoje "accessories_to_rooms"?

  1. SELECT
  2. vtiger_crmentityrel.crmid AS id_klienta,
  3. vtiger_crmentityrel.relcrmid AS id_zdarzenia,
  4. vtiger_activity.subject,
  5. vtiger_activity.eventstatus
  6. FROM vtiger_activity
  7. JOIN vtiger_crmentityrel
  8. WHERE EXISTS (
  9. SELECT vtiger_crmentityrel.relcrmid
  10. FROM vtiger_crmentityrel
  11. WHERE vtiger_crmentityrel.relcrmid = vtiger_activity.activityid
  12. GROUP BY vtiger_crmentityrel.relcrmid
  13. HAVING COUNT(vtiger_crmentityrel.relcrmid) = 1
  14. )


Ten post edytował Grzeniu 30.10.2017, 11:36:25
Go to the top of the page
+Quote Post
trueblue
post 30.10.2017, 19:05:15
Post #4





Grupa: Zarejestrowani
Postów: 6 761
Pomógł: 1822
Dołączył: 11.03.2014

Ostrzeżenie: (0%)
-----


A jaki wynik daje oryginalne zapytanie bez łączenia z tabelą vtiger_activity?


--------------------
Go to the top of the page
+Quote Post
sabat24
post 30.10.2017, 19:16:46
Post #5





Grupa: Zarejestrowani
Postów: 175
Pomógł: 26
Dołączył: 13.09.2007
Skąd: Gdańsk

Ostrzeżenie: (0%)
-----


Ja nie używam JOINa do pobierania wyników, więc u mnie go nie ma. Możliwe, że tu jest problem. Pisałem Ci PW. Prześlij mi kawałek swoich tabel z danymi, to zerknę na to u siebie.

Edit:

Cytat
FROM accessories_to_rooms a2r WHERE
Czym jest w moim przypadku twoje "accessories_to_rooms"?


U mnie:
rooms to są Twoi klienci, gdzie r_id jest ich kluczem primary - Twój crmid
accessories to u mnie Twoje relacje, czyli Z5, Z4 - Twój klucz to relcrmid
accessories_to_rooms to jest tabela relacyjna o postaci

Kod
room_id (Twój crmid) | accessory_id (Twój relcrmid)
K_1 | Z_1
K_1 | Z_2
K_2 | Z_3


Co oznacza, że klient K_1 posiada 2 relacje (Z_1 i Z_2), a klient K_2, posiada tylko Z_3. Robię więc podzapytania, które zlicza mi liczbę poszczególnych relacji z tabeli trzymającej relacje, dla każdego wiersza Twojego klienta.

Spróbój tez zrobić aliasy, by podzapytanie nie korzystało z Twojego JOINa z linijki 7, do tego JOINa dodaj swoje powiązanie. Piszę z ręki, ale raczej powinno to wyglądać tak:

  1. SELECT
  2. vc.crmid AS id_klienta,
  3. vc.relcrmid AS id_zdarzenia,
  4. va.subject,
  5. va.eventstatus
  6. FROM vtiger_activity va
  7. JOIN vtiger_crmentityrel vc ON (vc.relcrmid = va.activityid)
  8. WHERE EXISTS (
  9. SELECT vc2.relcrmid
  10. FROM vtiger_crmentityrel vc2
  11. WHERE vc2.relcrmid = va.activityid
  12. GROUP BY vc2.relcrmid
  13. HAVING COUNT(vc2.relcrmid) = 1
  14. )


Ten post edytował sabat24 30.10.2017, 23:28:22
Go to the top of the page
+Quote Post

Reply to this topicStart new topic
1 Użytkowników czyta ten temat (1 Gości i 0 Anonimowych użytkowników)
0 Zarejestrowanych:

 



RSS Wersja Lo-Fi Aktualny czas: 25.04.2024 - 12:39