¿SELECCIONAR DISTINCT en una columna, mientras devuelve las otras columnas?


12

Tengo una consulta que usa tres tablas de búsqueda para obtener toda la información que necesito. Necesito tener DISTINCTvalores para una columna, sin embargo, también necesito el resto de los datos asociados con ella.

Mi 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;

Quiero obtener todos los productos de esta consulta, pero solo quiero obtenerlos una vez porque estoy completando un menú desplegable para una aplicación de búsqueda. Quiero que el usuario pueda seleccionar entre los productos que están en esa tabla (es por eso que solo los necesito una vez).

¿Es esto demasiado complicado? ¿Debo usar un enfoque más simplificado?


Pero un producto está relacionado con muchos documentos. Y su consulta los devuelve todos (documentos para un producto). ¿Cuál debería ser elegido?
ypercubeᵀᴹ

Respuestas:


7

Un enfoque más no mencionado aún es usar funciones de ventana, por ejemplo 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- ¡Gracias! Eso funciono. Cada vez que intenté adaptar algún ejemplo de la red, fueron mis uniones lo que me confundió, pero creo que lo entiendo ahora.
stephmoreland

Sería mejor hacer las uniones fuera de la subconsulta si no es lo que hace que los datos sean "distintos", para minimizar los datos que consulta y duplicar solo para "desecharlos" seleccionando num = 1 en la función de ventana.
Allan S. Hansen el

4

Hay algunas formas de hacer esto. Las dos principales que uso son expresiones de tabla comunes y subconsultas. Usando un CTE, su consulta se vería así:

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

Normalmente pruebo para ver cuál es más rápido y voy con ese.

Espero que esto te ayude.


Pensé que entendía su respuesta, así que la probé (la primera), pero creo que mis uniones están causando un problema con las uniones de su solución.
stephmoreland

¿Cuál es la columna que debe ser distinta? Publicaré una solución más completa para usted.
Mr.Brownstone

product.displayheading es la columna
stephmoreland

1

(Creo que lo que está intentando hacer es "colapsar" cada fila de resultados en un solo producto, por lo que esta respuesta se basa en esa suposición).

Esto no es posible. Para obtener los datos relacionados con 1 .. * de las otras tablas, debe devolver valores duplicados en las otras columnas.

Generalmente, la forma de manejar esto es ejecutar la consulta tal como está y procesar el conjunto de resultados unidos en el código de la aplicación. Por lo general, hago esto utilizando un enfoque de colección hash que termina con entidades distintas de cada tipo en una colección basada en un valor clave.

Si bien este enfoque cuesta más en términos de tráfico de red, generalmente es preferible hacer algo como ejecutar múltiples consultas y unir los resultados según lo necesite en el código de la aplicación. Depende de muchos factores, incluida la frecuencia con la que se ejecutan las consultas y la cantidad de datos que se devuelven.

Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.