Używanie instrukcji SELECT w klauzuli WHERE innej instrukcji SELECT

21

Stworzyłem projekt zdalnej aplikacji na libpq dla PostrgreSQL . Zachowuje się dobrze, ale profilowałem ogólne działanie aplikacji. Dla każdego końcowego wyniku biznesowego, który produkuję, zdarza się, że nazywam coś w rodzaju klauzuli 40 wyboru (ponad tcpip).

Mam wspomnienia z SQL-Servera przypominające mi o zminimalizowaniu liczby interakcji między moją zdalną aplikacją a bazą danych. Po przeanalizowaniu moich selekcji myślę, że mógłbym zmniejszyć tę liczbę do 3 SELECTklauzul, używając sprzężeń. Ale nie pamiętam składni użycia wyniku SELECTw innym SELECT.

Na przykład:

SELECT * FROM individual
INNER JOIN publisher
ON individual.individual_id = publisher.individual_id
WHERE individual.individual_id = 'here I would like to use the results of a another select'

Ten drugi SELECTbyłby po prostu tego rodzaju:

SELECT identifier FROM another_table WHERE something='something'

Oto uproszczony układ tabel, kilkakrotnie odrzucany dla różnych typów item_ ... (3 zupełnie różne typy, stąd 3 zapytania SQL, jeśli są zoptymalizowane).

table passage
  id_passage PK
  business_field_passage bytea

table item
  id_item PK
  id_passage FK
  business_field_item text

table item_detail
  id_item_detail PK
  id_item FK
  business_field_item_detail text
  image_content bytea

Istnieje kilka id_itemdla jednego id_passage.
Istnieje kilka id_item_detaildla jednego id_item.

Jak byś to napisał?
Jak nazywa się opis przekierowania jednego wyboru do drugiego (jeśli istnieje)?

Stephane Rolland
źródło
czy odnosisz się do 7.2.1.3. Podzapytania?
Stephane Rolland
Być może tak, wraz z częścią JOIN.
dezso

Odpowiedzi:

30

Czy to jest to, do czego dążysz? Upewnij się, że porównywane pola są porównywalne (tzn. Oba pola są numeryczne, tekstowe, logiczne itp.).

SELECT * FROM Individual
INNER JOIN Publisher
ON Individual.IndividualId = Publisher.IndividualId
WHERE Individual.IndividualId = (SELECT someID FROM table WHERE blahblahblah)

Jeśli chcesz wybrać na podstawie wielu wartości:

SELECT * FROM Individual
INNER JOIN Publisher
ON Individual.IndividualId = Publisher.IndividualId
WHERE Individual.IndividualId IN (SELECT someID FROM table WHERE blahblahblah)
Angry Spartan
źródło
czy to może być takie proste? czy to nadal działa, jeśli SELECT someID FROM table WHERE blahblahblahma wiele rekordów? Sprawdzę to teraz.
Stephane Rolland
Które zapytanie wybiera wiele rekordów? Może działać, jeśli wybierzesz wiele rekordów, ale jeśli możesz nam pokazać swoje układy tabel, które pomogłyby nam dopracować odpowiedź.
Angry Spartan
1
WHERE Individual.IndividualId IN...wygląda dobrze.
Stephane Rolland
10

Możesz po prostu przepisać to jako inne JOIN . Jest to zwykle najprostsze i najszybsze:

SELECT i.*, p.*
FROM   individual    i
JOIN   publisher     p USING (individualid)
JOIN   another_table a ON a.identifier = i.individualid
WHERE  a.something = 'something'

Uprościłem też nieco i wyeliminowałem darmową pisownię identyfikatorów CamelCase.

Erwin Brandstetter
źródło
1
Tak to. Umieram trochę w środku, gdy widzę składnię IN (SELECT ..).
Mark Storey-Smith
@ MarkStorey-Smith Czy masz na myśli, że jest to więcej niż prostsze i szybsze: jest to standard kodowania SQL, aby użyć innego joinzamiast zamiast in ( select...)W takim przypadku powinienem również przypisać dobrą odpowiedź Erwinowi.
Stephane Rolland
1
@StephaneRolland Czy szybkość będzie zależała od platformy i wersji. Na przykład SQL Server 2008+ wygeneruje identyczne plany wykonania dla INNER JOIN i IN (SELECT ...). Nie mam pojęcia, czy to samo dotyczy PostgreSql. Pomijając wydajność, styl IN (SELECT ...) sprawia, że ​​zastanawiam się, czy autor w pełni zrozumiał semantykę i koncepcje SQL. AngrySpartan poprawnie odpowiedział na twoje pierwotne pytanie. ErwinBrandstetter pokazał ci, jak powinieneś to zrobić :).
Mark Storey-Smith
6
@ MarkStorey-Smith: JOIN nie zawsze jest równoważny warunkowi IN. Pytanie nie jest takie, które jest szybsze, pytanie, które jest poprawne.
a_horse_w_no_name