SELECT DISTINCT w jednej kolumnie, zwracając pozostałe kolumny?

12

Mam zapytanie, które wykorzystuje trzy tabele wyszukiwania, aby uzyskać wszystkie potrzebne informacje. Muszę mieć DISTINCTwartości dla jednej kolumny, ale potrzebuję również pozostałych danych z nią związanych.

Mój kod SQL:

SELECT acss_lookup.ID AS acss_lookupID,
   acss_lookup.product_lookupID AS acssproduct_lookupID,
   acss_lookup.region_lookupID AS acssregion_lookupID,
   acss_lookup.document_lookupID AS acssdocument_lookupID,
   product.ID AS product_ID,
   product.parent_productID AS productparent_product_ID,
   product.label AS product_label,
   product.displayheading AS product_displayheading,
   product.displayorder AS product_displayorder,
   product.display AS product_display,
   product.ignorenewupdate AS product_ignorenewupdate,
   product.directlink AS product_directlink,
   product.directlinkURL AS product_directlinkURL,
   product.shortdescription AS product_shortdescription,
   product.logo AS product_logo,
   product.thumbnail AS product_thumbnail,
   product.content AS product_content,
   product.pdf AS product_pdf,
   product.language_lookupID AS product_language_lookupID,
   document.ID AS document_ID,
   document.shortdescription AS document_shortdescription,
   document.language_lookupID AS document_language_lookupID,
   document.document_note AS document_document_note,
   document.displayheading AS document_displayheading
FROM acss_lookup
     INNER JOIN product ON (acss_lookup.product_lookupID = product.ID)
     INNER JOIN document ON (acss_lookup.document_lookupID = document.ID)
ORDER BY product_displayheading ASC;

Chcę uzyskać wszystkie produkty z tego zapytania, ale chcę je uzyskać tylko raz, ponieważ wypełniam menu rozwijane aplikacji wyszukującej. Chcę, aby użytkownik mógł wybrać produkty znajdujące się w tej tabeli (dlatego potrzebuję ich tylko raz).

Czy to jest zbyt skomplikowane? Czy powinienem zastosować bardziej uproszczone podejście?

Stephmoreland
źródło
Ale produkt jest powiązany z wieloma dokumentami. A zapytanie zwraca je wszystkie (dokumenty dotyczące produktu). Który wybrać?
ypercubeᵀᴹ

Odpowiedzi:

7

Jeszcze jednym podejściem, o którym jeszcze nie wspomniano, jest użycie funkcji okna, na przykład numer_wiersza:

   SELECT * FROM  
   (
   SELECT acss_lookup.ID AS acss_lookupID, 
   ROW_NUMBER() OVER 
   (PARTITION BY your_distinct_column ORDER BY any_column_you_think_is_appropriate)
   as num,
   acss_lookup.product_lookupID AS acssproduct_lookupID,
   acss_lookup.region_lookupID AS acssregion_lookupID,
   acss_lookup.document_lookupID AS acssdocument_lookupID,
   product.ID AS product_ID,
   product.parent_productID AS productparent_product_ID,
   product.label AS product_label,
   product.displayheading AS product_displayheading,
   product.displayorder AS product_displayorder,
   product.display AS product_display,
   product.ignorenewupdate AS product_ignorenewupdate,
   product.directlink AS product_directlink,
   product.directlinkURL AS product_directlinkURL,
   product.shortdescription AS product_shortdescription,
   product.logo AS product_logo,
   product.thumbnail AS product_thumbnail,
   product.content AS product_content,
   product.pdf AS product_pdf,
   product.language_lookupID AS product_language_lookupID,
   document.ID AS document_ID,
   document.shortdescription AS document_shortdescription,
   document.language_lookupID AS document_language_lookupID,
   document.document_note AS document_document_note,
   document.displayheading AS document_displayheading
   FROM acss_lookup
     INNER JOIN product ON (acss_lookup.product_lookupID = product.ID)
     INNER JOIN document ON (acss_lookup.document_lookupID = document.ID)
   )a
   WHERE a.num = 1
   ORDER BY product_displayheading ASC;
a1ex07
źródło
@ a1ex07- Dzięki! To się udało. Za każdym razem, gdy próbowałem zaadaptować jakiś przykład z sieci, moje POŁĄCZENIA wprawiały mnie w zakłopotanie, ale myślę, że teraz to rozumiem.
stephmoreland
Lepiej byłoby wykonać sprzężenia poza podzapytaniem, jeśli nie to, co czyni dane „odrębnymi”, aby zminimalizować dane, o które pytasz, i powielić je tylko, aby „wyrzucić”, wybierając num = 1 z funkcji okna.
Allan S. Hansen
4

Można to zrobić na kilka sposobów. Dwoma głównymi, których używam, są wspólne wyrażenia tabelowe i zapytania cząstkowe. Za pomocą CTE twoje zapytanie wyglądałoby mniej więcej tak:

WITH theResultSet AS
(
    SELECT DISTINCT(column) AS col1 FROM some.table
)
SELECT whatever
  FROM more.data AS a
  JOIN theResultSet as b ON a.col1 = b.col1
  /* additional joins, clauses etc...*/

Lub używając podkwerendy:

SELECT whatever
  FROM more.data AS a
  JOIN (SELECT DISTINCT(column) AS col1 FROM some.table) AS b ON a.col1 = b.col1
/* additional joins, clauses etc... */

Zwykle testuję, aby zobaczyć, która jest szybsza i idę z tym.

Mam nadzieję, że to Ci pomoże.

Mr.Brownstone
źródło
Myślałem, że rozumiem twoją odpowiedź, więc wypróbowałem ją (pierwszą), ale myślę, że moje DOŁĄCZENIA powodują problem z DOŁĄCZONYMI rozwiązaniami.
stephmoreland,
jaka kolumna musi być odrębna? Opublikuję dla ciebie bardziej kompleksowe rozwiązanie.
Mr.Brownstone
product.displayheading to kolumna
stephmoreland
1

(Myślę, że to, co próbujesz zrobić, to „zwinąć” każdy wiersz wyników do jednego produktu, więc ta odpowiedź opiera się na tym założeniu.)

To jest niemożliwe. Aby uzyskać powiązane dane 1 .. * z innych tabel, musisz zwrócić zduplikowane wartości w innych kolumnach.

Ogólnie rzecz biorąc, sposobem na poradzenie sobie z tym jest uruchomienie zapytania w obecnej postaci i przetworzenie połączonego zestawu wyników w kodzie aplikacji. Zazwyczaj robię to przy użyciu metody gromadzenia skrótów, która kończy się odrębnymi jednostkami każdego typu w kolekcji opartej na kluczowej wartości.

Chociaż takie podejście kosztuje więcej pod względem ruchu sieciowego, zwykle lepiej jest zrobić coś takiego, jak uruchamianie wielu zapytań i łączenie wyników zgodnie z potrzebami w kodzie aplikacji. Zależy to od wielu czynników, w tym od częstotliwości uruchamiania zapytań / zapytań i ilości zwracanych danych.

Jon Seigel
źródło