2008-10-30 14 views
14

Agregado: Trabajando con SQL Server 2000 y 2005, por lo que tiene que funcionar en ambos. Además, value_rk no es un número/entero (Error: el identificador único del tipo de datos del operando no es válido para el operador mínimo)Seleccione una columna SQL DISTINCT

¿Hay alguna manera de hacer una sola columna "DISTINCT" coincidir cuando no me importan las otras columnas devueltas ? Ejemplo:

**Table** 
Value A, Value L, Value P 
Value A, Value Q, Value Z 

Necesito devolver solo una de estas filas según lo que está en la primera (Valor A). Todavía necesito resultados de la segunda y la tercera columna (la segunda debería coincidir en todos los ámbitos, pero la tercera es una clave única, de la que necesito al menos uno).

Esto es lo que tengo hasta ahora, a pesar de que, obviamente, no funciona:

SELECT value, attribute_definition_id, value_rk 
FROM attribute_values 
WHERE value IN (
    SELECT value, max(value_rk) 
    FROM attribute_values 
) 
ORDER BY attribute_definition_id 

estoy trabajando en ColdFusion así que si hay una solución simple, ya que estoy abierto a eso también . Estoy intentando limitar o "agrupar por" la primera columna "valor". value_rk es mi gran problema ya que cada valor es único, pero solo necesito uno.

NOTA: value_rk no es un número, por lo tanto, esto no funciona

ACTUALIZACIÓN: Tengo una versión de trabajo, es probable que sea un poco más lento que una versión de SQL puro, pero la verdad es todo lo que esté en este momento es mejor que nada Toma los resultados de la primera consulta, realiza una segunda consulta, excepto limitar los resultados a uno, y toma una value_rk correspondiente para el valor que coincida. De esta manera:

<cfquery name="queryBaseValues" datasource="XXX" timeout="999"> 
    SELECT DISTINCT value, attribute_definition_id 
    FROM attribute_values 
    ORDER BY attribute_definition_id 
</cfquery> 

<cfoutput query="queryBaseValues"> 
    <cfquery name="queryRKValue" datasource="XXX"> 
     SELECT TOP 1 value_rk 
     FROM attribute_values 
     WHERE value = '#queryBaseValues.value#' 
    </cfquery> 
    <cfset resourceKey = queryRKValue.value_rk> 
    ... 

Así que ahí lo tienes, seleccionando una sola columna distintivamente en ColdFusion. Cualquier sugerencia pura de SQL Server 2000/2005 es aún muy bienvenida :)

+0

¿Puede aclarar lo que necesita? Cualquier fila, pero solo una fila por valor? ¿La fila con el valor que tiene value_rk máximo? No estoy seguro de entender lo que estás buscando aquí. – tvanfosson

+0

> NOTA: value_rk no es un número, por lo tanto, esto NO FUNCIONA. Eso no tiene nada que ver con por qué falla su consulta. No ha mencionado el RDBMS que está utilizando, pero en Oracle puede usar MAX en las columnas de caracteres. –

+0

MS SQL también puede usar MAX en columnas no numéricas. – BradC

Respuesta

11

esto podría funcionar:

SELECT DISTINCT a.value, a.attribute_definition_id, 
    (SELECT TOP 1 value_rk FROM attribute_values WHERE value = a.value) as value_rk 
FROM attribute_values as a 
ORDER BY attribute_definition_id 

.. no evaluados.

+1

Funciona en MS SQL para mí . – Steffen

1
SELECT value, attribute_definition_id, value_rk 
FROM attribute_values 
WHERE value, value_rk IN (
     SELECT value, max(value_rk) 
     FROM attribute_values 
     GROUP BY value 
) 
ORDER BY attribute_definition_id 

¡NO EXHAUSTA!

+0

Mi error, publiqué sin probarlo, actualicé que value_rk no es un número (max/min won ' t trabajar en él) – Organiccat

+0

max/min funcionará en valores varchar en SQL2005. ¿Qué db estás usando? – BradC

+0

Realizando pruebas en 2005, pero el servidor de producción es 2000. Aparece un error de coincidencia de tipo de datos al intentar ejecutar min/max en él (agregado a la parte superior de la publicación de OP). – Organiccat

2

¿Esto es lo que estás buscando?

SELECT value, attribute_definition_id, value_rk 
FROM attribute_values av1 
WHERE value_rk IN (
     SELECT max(value_rk) 
     FROM attribute_values av2 
     WHERE av2.value = av1.value 
) 
ORDER BY attribute_definition_id 

Si value_rk es único, esto debería funcionar.

8
SELECT a1.value, a1.attribute_definition_id, a1.value_rk 
FROM attribute_values AS a1 
    LEFT OUTER JOIN attribute_values AS a2 
    ON (a1.value = a2.value AND a1.value_rk < a2.value_rk) 
WHERE a2.value IS NULL 
ORDER BY a1.attribute_definition_id; 

En otras palabras, buscar la fila a1 para los que no existe ninguna fila a2 con el mismo value y una mayor value_rk.

+0

Esta es una gran solución porque funcionará con la mayoría (¿todos?) RDBMS. Me he echado a perder por 'DISTINCT ON' de PostgreSQL que es simple de escribir, pero no es estándar y no está implementado en SQL Server, entre otros. – Sam

1

no estoy seguro si entiendo completamente su puesta a punto, pero sería algo así como este trabajo:

SELECT value, attribute_definition_id, value_rk 
FROM attribute_values 
GROUP BY value 
ORDER BY attribute_definition_id; 

Una vez más, no estoy muy seguro de qué columna es lo que estamos tratando de limitar o cómo quieres limitarlo.

8

Esto debería funcionar para PostgreSQL, no sé qué dbms usa.

SELECT DISTINCT ON (value) 
    value, 
    attribute_definition_id, 
    value_rk 
FROM 
    attribute_values 
ORDER BY 
    value, 
    attribute_definition_id 

PostgreSQL Docs

+4

El único problema aquí es que MS-SQL no conoce DISTINCT ON, solo DISTINCT en todas las columnas seleccionadas ... –

2

Bueno, aquí está mi hipótesis:

SQL Server Standard

value_rk no es un valor numérico, pero de valor y attribute_definition_id son numérico.

SELECT value_rk, MIN(value) as value, MIN(attribute_definition_id) as attribute_definition_id 
FROM attribute_values 
GROUP BY value_rk 
ORDER BY MIN(attribute_definition_id) 

Si uno de esos campos no es numérico, entonces se va a requerir más pensamiento - por favor háganoslo saber.

0

Menos elegante de lo que me gustaría ---- es esencialmente lo que estás haciendo, solo en SQL puro --- pero funciona y todo se puede hacer en SQL.

 
DECLARE @mytable TABLE(mykey NVARCHAR(512), myVal NVARCHAR(512)) 

DECLARE @keyVal NVARCHAR(512) 
DECLARE @depVal NVARCHAR(512) 
DECLARE myCursor CURSOR for 
    SELECT DISTINCT(value) FROM attribute_values 
OPEN myCursor 
FETCH NEXT FROM myCursor INTO @keyVal 
WHILE @@FETCH_STATUS=0 
    BEGIN 
    SET @depVal = (SELECT TOP 1 attribute_definition_id FROM attribute_values WHERE [email protected] ORDER BY attribute_definition_id) 
    INSERT INTO @mytable (mykey, myVal) VALUES (@keyVal, @depVal) 
    FETCH NEXT FROM myCursor INTO @keyVal 
    END 
DEALLOCATE myCursor 

SELECT * FROM @mytable 

Puede agregar un depVal2 y otros usando este método.

2

Si usted está abierto a la utilización de las variables de tabla, se puede mantener todo dentro de una sola llamada base de datos de la siguiente manera:

DECLARE @attribute_values TABLE (value int, attribute_definition_id int, value_rk uniqueidentifier) 

INSERT INTO @attribute_values (value) 
SELECT DISTINCT value FROM attribute_values 

UPDATE @attribute_values 
SET attribute_definition_id = av2.attribute_definition_id, 
    value_rk = av2.value_rk 
FROM @attribute_values av1 
INNER JOIN attribute_values av2 ON av1.value = av2.value 

SELECT value, attribute_definition_id, value_rk FROM @attribute_values 

Esencialmente va a crear un conjunto de registros limitada con la mesa llena de valores únicos de 'valor ', y dejar que SQL Server llene las lagunas usando solo una de las coincidencias de la tabla principal.

Editado para agregar: Esta sintaxis funciona perfectamente en cfquery.

0

Creo

SELECT DISTINCT a.value, a.attribute_definition_id, 
(SELECT TOP 1 value_rk FROM attribute_values WHERE value = a.value) as value_rk 
FROM attribute_values as a 
ORDER BY attribute_definition_id 

trabajaron

0

Como se ha señalado por John Fiala, la respuesta canónica en el servidor SQL es utilizar una cláusula group by cuando se quiere realizar una operación de "clara" sobre un subconjunto de columnas ¿Por qué es esta la respuesta canónica correcta? Bueno, desea obtener columnas que no sean parte de su grupo "distinto". ¿Exactamente qué filas desea obtener para estas columnas subsidiarias? El uso de una cláusula group by y la definición de funciones agregadas para estas columnas subsidiarias hace que su consulta se comporte correctamente en el sentido de que ahora sabe cómo se obtienen estas columnas subsidiarias. En este artículo se da más detalles:

http://weblogs.sqlteam.com/jeffs/archive/2007/10/12/sql-distinct-group-by.aspx

SELECT value_rk, MIN(value) as value, 
MIN(attribute_definition_id) as attribute_definition_id 
FROM attribute_values 
GROUP BY value_rk 

Además, vale la pena señalar que el MIN y MAX trabajo en los textos y varios otros tipos de datos que no son valores numéricos.

Cuestiones relacionadas