Seleccione una columna DISTINCT SQL
-
05-07-2019 - |
Pregunta
Añadido: Trabajar con SQL Server 2000 y 2005, por lo que tiene que trabajar 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)
¿Hay alguna forma de hacer una sola columna " DISTINCT " ¿Coincide 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 tercera columnas (la segunda debería coincidir con todas las áreas de todos modos, pero la tercera es una clave única, que necesito al menos una).
Esto es lo que tengo hasta ahora, aunque 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, también estoy abierto a eso. 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 que funciona, probablemente sea un poco más lenta que una versión SQL pura, pero honestamente, cualquier cosa que funcione en este punto es mejor que nada. Toma los resultados de la primera consulta, realiza una segunda consulta, excepto que limita los resultados a uno, y toma un valor_rk correspondiente para el valor que coincide. Al igual que:
<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 tienen, seleccionando una sola columna de forma distinta en ColdFusion. Cualquier sugerencia pura de SQL Server 2000/2005 es muy bienvenida :)
Solución
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 probado.
Otros consejos
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, busque la fila a1
para la cual no existe ninguna fila a2
con el mismo valor
y una mayor value_rk .
Esto debería funcionar para PostgreSQL, no sé qué dbms usas.
SELECT DISTINCT ON (value)
value,
attribute_definition_id,
value_rk
FROM
attribute_values
ORDER BY
value,
attribute_definition_id
¿Es esto 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.
Bien, aquí están mis suposiciones:
Servidor SQL estándar
value_rk no es un valor numérico, pero value y attribute_definition_id son numeric.
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, se requerirá más reflexión, háganoslo saber.
Si está abierto a usar variables de tabla, puede mantenerlo todo dentro de una sola llamada de base de datos como esta:
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, está creando un conjunto de registros limitado con la tabla llena de valores únicos de 'valor', y dejando que SQL Server complete los vacíos usando solo una de las coincidencias de la tabla principal.
Editado para agregar: esta sintaxis funciona bien dentro de cfquery.
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 PROBADO!
No estoy seguro si entiendo completamente su configuración, pero algo como esto funcionaría:
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 la que estás intentando limitar, o cómo quieres limitarla.
Menos elegante de lo que me gustaría: es básicamente lo que estás haciendo, solo en SQL puro, pero funciona y todo puede hacerse 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 VALUE=@keyVal 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
Puedes agregar un depVal2 y otros usando este método.
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
trabajado
Como lo señaló John Fiala, la respuesta canónica en el servidor SQL es usar una cláusula grupo por grupo cuando desee realizar una " distinta " Operación sobre un subconjunto de columnas. ¿Por qué es esta la respuesta canónica correcta? Bueno, desea arrastrar columnas que no forman parte de su " distintas " grupo. ¿Exactamente qué filas desea obtener para estas columnas subsidiarias? El uso de una cláusula por grupo y la definición de funciones agregadas para estas columnas subsidiarias hace que su consulta se comporte bien en el sentido de que ahora sabe cómo se obtienen estas columnas subsidiarias. Este artículo 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 tener en cuenta que MIN y MAX funcionan con texto y varios otros tipos de datos que no son valores numéricos.