Zapytanie bez użycia JOIN

0

Cześć. Potrzebuje coś na szybko dlatego z góry przepraszam, że nie zapoznałem się z regulaminem forum i być może wrzucam coś w nieodpowiednie miejsce.

Meritum.

Mam skomplikowane zapytanie i niestety przy testach działa jak dla mnie zbyt wolno, stąd postanowiłem rozdzielić je na dwa, co przyniosło efekt, ale to pierwsze chciałbym jeszcze usprawnić.

Mam tabelę relacji ( int )

| id_1 | id_2 |

Chciałbym wyciągnąć rzędy unikalnych id_1 które są częścią wspólną kilku warunków dla id_2. Czyli w uproszczeniu id_1 dla ( id_2 IN ( value1, value2, value3 ) AND id_2 IN ( value4, value5 ) ). Chciałbym znaleźć takie id_1 którego id_2 zawiera się w pierwszym zbiorze i w drugim. Do tej pory robię to przez JOIN i przy milionowych ilościach rzędów, zastanawiam się czy jest prostsze i szybsze rozwiązanie.

Dziękuję i pozdrawiam.

0

Chyba chodzi ci o coś w ten deseń:

SELECT id_1 FROM tabela WHERE id_2 IN (value1, value2, value3, value4, value5) GROUP BY id_1 HAVING Count(Distinct CASE WHEN id_2 IN (value1, value2, value3) THEN 1 ELSE 2 END)=2
1

Za wolno czy nie za wolno, zobacz na plan zapytania, może przy obecnej strukturze danych nie da się szybciej. A może się da, wtedy plan zapytania podpowie, jak to zrobić.

0

Marcin.Miga

Dziękuję, rzeczywiście jest to rozwiązanie słuszne i szybsze niż moje rozbicie na kilka zapytań i działanie na tablicach poprzez array_intersect. Jeśli jeszcze mógłbym zapytać jak wyglądałoby to gdybym miał więcej części wspólnych załóżmy 3,4. Byłbyś w stanie wskazać drogę?

Marcin.Miga napisał(a):

Chyba chodzi ci o coś w ten deseń:

SELECT id_1 FROM tabela WHERE id_2 IN (value1, value2, value3, value4, value5) GROUP BY id_1 HAVING Count(Distinct CASE WHEN id_2 IN (value1, value2, value3) THEN 1 ELSE 2 END)=2
0

Napiszę inaczej, byś wiedział skąd się co wzięło...
Dla 2 grup:

SELECT id_1 
FROM tabela 
WHERE 
   id_2 IN (value1, value2, value3)
   OR
   id_2 IN (value4, value5) 
GROUP BY id_1 
HAVING 
   COUNT(DISTINCT 
      CASE 
         WHEN id_2 IN (value1, value2, value3) THEN 1 
         WHEN id_2 IN (value4, value5) THEN 2 
      END)
   =2

Dla 3 grup:

SELECT id_1 
FROM tabela 
WHERE 
   id_2 IN (value1, value2, value3)
   OR
   id_2 IN (value4, value5) 
   OR
   id_2 IN (value6, value7, value8) 
GROUP BY id_1 
HAVING 
   COUNT(DISTINCT 
      CASE 
         WHEN id_2 IN (value1, value2, value3) THEN 1 
         WHEN id_2 IN (value4, value5) THEN 2 
         WHEN id_2 IN (value6, value7, value8)  THEN 3
      END)
   =3

Ale że OR jest w miarę wolny, więc od razu łączędo wspólnego zbioru IN, czyli zamieniam id_2 IN (value1, value2, value3) OR id_2 IN (value4, value5) OR id_2 IN (value6, value7, value8) na id_2 IN (value1, value2, value3, value4, value5, value6, value7, value8)
Dla 4 grup: (już z zamienionym OR)

SELECT id_1 
FROM tabela 
WHERE 
   id_2 IN (value1, value2, value3, value4, value5, value6, value7, value8, value9, value10)
GROUP BY id_1 
HAVING 
   COUNT(DISTINCT 
      CASE 
         WHEN id_2 IN (value1, value2, value3) THEN 1 
         WHEN id_2 IN (value4, value5) THEN 2 
         WHEN id_2 IN (value6, value7, value8)  THEN 3
         WHEN id_2 IN (value9, value10) THEN 4 
      END)
   =4

1 użytkowników online, w tym zalogowanych: 0, gości: 1