ВЫБЕРИТЕ DISTINCT в одном столбце, возвращая другие столбцы?

12

У меня есть запрос, который использует три таблицы поиска, чтобы получить всю необходимую информацию. Мне нужно иметь DISTINCTзначения для одного столбца, однако мне также нужны остальные данные, связанные с ним.

Мой код 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;

Я хочу получить все продукты из этого запроса, но я хочу получить их только один раз, потому что я заполняю раскрывающееся меню для приложения поиска. Я хочу, чтобы пользователь мог выбирать продукты из этой таблицы (поэтому они нужны мне только один раз).

Это слишком сложно? Должен ли я использовать более упрощенный подход?

stephmoreland
источник
Но продукт связан со многими документами. И ваш запрос возвращает их все (документы на продукт). Какой из них должен быть выбран?
ypercubeᵀᴹ

Ответы:

7

Еще один не упомянутый подход заключается в использовании оконных функций, например row_number:

   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
источник
@ a1ex07- Спасибо! Это сработало. Каждый раз, когда я пытался приспособить какой-то пример из сети, меня смутили мои СОЕДИНЕНИЯ, но я думаю, что понял это сейчас.
Stephmoreland
Было бы лучше сделать объединения вне подзапроса, если не то, что делает данные «отличимыми», чтобы минимизировать данные, которые вы запрашиваете, и дублировать их только для «отбрасывания», выбрав num = 1 из оконной функции.
Аллан С. Хансен
4

Есть несколько способов сделать это. Два основных, которые я использую - это обычные табличные выражения и подзапросы. При использовании CTE ваш запрос будет выглядеть примерно так:

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...*/

Или используя подзапрос:

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... */

Я обычно проверяю, что быстрее, и иду с этим.

Я надеюсь, это поможет вам.

Mr.Brownstone
источник
Я думал, что понял ваш ответ, поэтому я попробовал его (первый), но я думаю, что мои СОЕДИНЕНИЯ вызывают проблему с СОЕДИНЕНИЯМИ вашего решения.
Stephmoreland
какой столбец должен быть отчетливым? Я опубликую более полное решение для вас.
Мистер Браунстоун,
колонка product.displayheading
stephmoreland
1

(Я думаю, что вы пытаетесь «свернуть» каждую строку результатов в один продукт, поэтому этот ответ основывается на этом предположении.)

Это невозможно. Чтобы получить связанные данные 1 .. * из других таблиц, вы должны вернуть повторяющиеся значения в других столбцах.

Обычно способ справиться с этим - запустить запрос как есть и обработать объединенный набор результатов в коде приложения. Я обычно делаю это, используя подход сбора хешей, который заканчивается отдельными объектами каждого типа в коллекции на основе значения ключа.

Хотя этот подход стоит дороже с точки зрения сетевого трафика, обычно предпочтительнее выполнять что-то вроде выполнения нескольких запросов и сшивания результатов, как вам нужно в коде приложения. Это зависит от многих факторов, включая частоту выполнения запросов / запросов и объем возвращаемых данных.

Джон Сайгель
источник