SELECT DISTINCT em uma coluna, enquanto retorna as outras colunas?

12

Eu tenho uma consulta que usa três tabelas de pesquisa para obter todas as informações que eu preciso. Preciso ter DISTINCTvalores para uma coluna, no entanto, também preciso do restante dos dados associados a ela.

Meu código 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;

Desejo obter todos os produtos desta consulta, mas quero obtê-los apenas uma vez, porque estou preenchendo um menu suspenso para um aplicativo de pesquisa. Desejo que o usuário possa selecionar os produtos que estão nessa tabela (é por isso que só preciso deles uma vez).

Isso é muito complicado? Devo usar uma abordagem mais simplificada?

Stephmoreland
fonte
Mas um produto está relacionado a muitos documentos. E sua consulta retorna todos eles (documentos para um produto). Qual deles deve ser escolhido?
precisa saber é o seguinte

Respostas:

6

Uma outra abordagem ainda não mencionada é usar as funções da janela, por exemplo, 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
fonte
@ a1ex07- Obrigado! Isso funcionou. Toda vez que tentei adaptar algum exemplo da rede, foram minhas JOINS que me confundiram, mas acho que entendi agora.
stephmoreland
Seria melhor fazer as junções fora da subconsulta, se não o que torna os dados "distintos", para minimizar os dados consultados e duplicados apenas para "jogar fora" selecionando num = 1 na função da janela.
Allan S. Hansen,
4

Existem algumas maneiras de fazer isso. Os dois principais que eu uso são expressões e subconsultas comuns de tabela. Usando um CTE, sua consulta seria mais ou menos assim:

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

Ou usando uma subconsulta:

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

Eu normalmente testo para ver qual é mais rápido e vou com essa.

Espero que isso ajude você.

Mr.Brownstone
fonte
Pensei ter entendido sua resposta e tentei (a primeira), mas acho que minhas JOINS estão causando um problema com as JOINS da sua solução.
stephmoreland
qual é a coluna que precisa ser distinta? Vou postar uma solução mais abrangente para você.
Mr.Brownstone
product.displayheading é a coluna
stephmoreland
1

(Acho que o que você está tentando fazer é "recolher" cada linha de resultado em um único produto; portanto, essa resposta segue essa suposição.)

Isso não é possível. Para obter os dados 1 .. * relacionados das outras tabelas, você deve retornar valores duplicados nas outras colunas.

Geralmente, a maneira de lidar com isso é executar a consulta como está e processar o conjunto de resultados associado no código do aplicativo. Eu costumo fazer isso usando uma abordagem de coleção de hash que acaba com entidades distintas de cada tipo em uma coleção com base em um valor-chave.

Embora essa abordagem custe mais em termos de tráfego de rede, geralmente é preferível fazer algo como executar várias consultas e unir os resultados conforme necessário no código do aplicativo. Depende de muitos fatores, incluindo a frequência com que as consultas são executadas e a quantidade de dados retornados.

Jon Seigel
fonte