SELEZIONA DISTINCT su una colonna, restituendo le altre colonne?


12

Ho una query che utilizza tre tabelle di ricerca per ottenere tutte le informazioni di cui ho bisogno. Ho bisogno di avere DISTINCTvalori per una colonna, tuttavia ho bisogno anche del resto dei dati ad essa associati.

Il mio codice 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;

Voglio ottenere tutti i prodotti da questa query, ma voglio ottenerli solo una volta perché sto popolando un menu a discesa per un'applicazione di ricerca. Voglio che l'utente sia in grado di selezionare tra i prodotti che si trovano in quella tabella (ecco perché ne ho bisogno solo una volta).

È troppo complicato? Dovrei usare un approccio più semplificato?


Ma un prodotto è legato a molti documenti. E la tua query li restituisce tutti (documenti per un prodotto). Quale dovrebbe essere scelto?
ypercubeᵀᴹ

Risposte:


7

Un altro approccio non ancora menzionato è l'uso delle funzioni della finestra, ad esempio 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- Grazie! Ha funzionato Ogni volta che ho cercato di adattare alcuni esempi dalla rete, sono stati i miei JOIN a confondermi, ma penso di averlo capito ora.
Stephmoreland,

Sarebbe meglio eseguire i join all'esterno della sottoquery, se non ciò che rende i dati "distinti", in modo da ridurre al minimo i dati richiesti e duplicarli solo per "buttarli via" selezionando num = 1 dalla funzione finestra.
Allan S. Hansen,

4

Ci sono alcuni modi per farlo. Le due principali che utilizzo sono le espressioni di tabella comuni e le query secondarie. Utilizzando un CTE la tua query sarebbe simile a questa:

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

O usando una sottoquery:

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

Normalmente provo a vedere quale è più veloce e vado con quello.

Spero che questo ti aiuta.


Pensavo di aver capito la tua risposta, quindi l'ho provata (la prima), ma penso che i miei JOIN stiano causando un problema con i JOIN della tua soluzione.
Stephmoreland,

qual è la colonna che deve essere distinta? Pubblicherò una soluzione più completa per te.
Mr.Brownstone,

product.displayheading è la colonna
stephmoreland

1

(Penso che quello che stai cercando di fare sia "comprimere" ogni riga di risultati in un singolo prodotto, quindi questa risposta sta andando su tale presupposto.)

Non è possibile. Per ottenere i dati 1 .. * correlati dalle altre tabelle, è necessario restituire valori duplicati nelle altre colonne.

Generalmente il modo per gestirlo è eseguire la query così com'è ed elaborare il set di risultati unito nel codice dell'applicazione. Di solito lo faccio usando un approccio di raccolta hash che finisce con entità distinte di ciascun tipo in una raccolta basata su un valore chiave.

Mentre questo approccio costa di più in termini di traffico di rete, di solito è preferibile fare qualcosa come eseguire più query e unire i risultati di cui hai bisogno nel codice dell'applicazione. Dipende da molti fattori, tra cui la frequenza con cui vengono eseguite le query / query e la quantità di dati restituiti.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.