SELECT DISTINCT sur une colonne, tout en renvoyant les autres colonnes?

12

J'ai une requête qui utilise trois tables de recherche pour obtenir toutes les informations dont j'ai besoin. J'ai besoin d'avoir des DISTINCTvaleurs pour une colonne, mais j'ai également besoin du reste des données qui lui sont associées.

Mon code 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;

Je veux obtenir tous les produits de cette requête, mais je ne veux les obtenir qu'une seule fois car je remplis un menu déroulant pour une application de recherche. Je veux que l'utilisateur puisse choisir parmi les produits qui se trouvent dans ce tableau (c'est pourquoi je n'en ai besoin qu'une seule fois).

Est-ce trop compliqué? Dois-je utiliser une approche plus simplifiée?

stephmoreland
la source
Mais un produit est lié à de nombreux documents. Et votre requête les renvoie tous (documents pour un produit). Lequel devrait être choisi?
ypercubeᵀᴹ

Réponses:

7

Une autre approche non encore mentionnée consiste à utiliser des fonctions de fenêtre, par exemple 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
la source
@ a1ex07- Merci! Ça a marché. Chaque fois que j'essayais d'adapter un exemple du net, ce sont mes JOINS qui m'ont troublé, mais je pense que je comprends maintenant.
stephmoreland
Il serait préférable de faire les jointures en dehors de la sous-requête si ce n'est pas ce qui rend les données «distinctes», afin de minimiser les données que vous interrogez et dupliquez uniquement pour les «jeter» en sélectionnant num = 1 dans la fonction de fenêtre.
Allan S. Hansen
4

Il y a plusieurs façons de procéder. Les deux principales que j'utilise sont des expressions de table et des sous-requêtes courantes. En utilisant un CTE, votre requête ressemblerait à ceci:

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 en utilisant une sous-requête:

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

Je teste normalement pour voir lequel est le plus rapide et je choisis celui-là.

J'espère que ceci vous aide.

Mr.Brownstone
la source
Je pensais avoir compris votre réponse, alors je l'ai essayée (la première), mais je pense que mes JOINS sont à l'origine d'un problème avec les JOINS de votre solution.
stephmoreland
quelle est la colonne qui doit être distincte? Je publierai une solution plus complète pour vous.
Mr.Brownstone
product.displayheading est la colonne
stephmoreland
1

(Je pense que ce que vous essayez de faire est de "réduire" chaque ligne de résultat en un seul produit, donc cette réponse part de cette hypothèse.)

Ce n'est pas possible. Pour obtenir les données 1 .. * associées des autres tables, vous devez renvoyer des valeurs en double dans les autres colonnes.

Généralement, la façon de gérer cela consiste à exécuter la requête telle quelle et à traiter l'ensemble de résultats joint dans le code d'application. Je le fais généralement en utilisant une approche de collecte de hachage qui se termine par des entités distinctes de chaque type dans une collection basée sur une valeur clé.

Bien que cette approche coûte plus cher en termes de trafic réseau, il est généralement préférable de faire quelque chose comme exécuter plusieurs requêtes et assembler les résultats comme vous en avez besoin dans le code d'application. Cela dépend de nombreux facteurs, y compris la fréquence d'exécution de la ou des requêtes et la quantité de données renvoyées.

Jon Seigel
la source