¿Por qué SELECT DISTINCT * FROM tableno funciona para ti?
ypercubeᵀᴹ
19
Si su tabla tiene un PK, todas las filas deben ser distinctpor definición. Si está tratando de seleccionar, DISTINCT field1pero de alguna manera devolver todas las demás columnas, ¿qué debería suceder para aquellas columnas que tienen más de un valor para un field1valor en particular ? Tendría que usar GROUP BYy algún tipo de agregación en las otras columnas, por ejemplo.
Martin Smith
1
Si desea filas repetidas y no solo filas distintas, elimine la palabra clave distinta.
Hyperboreus
2
¿Podría dar un ejemplo de cómo espera que se vean los resultados? Hasta ahora, no puedo entender su consulta deseada.
Que ocasionalmente se puede escribir con una declaración distinta en:
selectdistincton field1 *fromtable
Sin embargo, en la mayoría de las plataformas, ninguno de los anteriores funcionará porque el comportamiento en las otras columnas no está especificado. (El primero funciona en MySQL, si eso es lo que está usando).
Puede buscar los distintos campos y seguir eligiendo una sola fila arbitraria cada vez.
En algunas plataformas (por ejemplo, PostgreSQL, Oracle, T-SQL), esto se puede hacer directamente usando funciones de ventana:
La consulta no se analizará para mí y da un error: The ranking function "row_number" must have an ORDER BY clause. Necesitamos agregar orden por cláusula después de la partición por campo1. Entonces la consulta correcta será select * from ( select *, row_number() over (partition by field1 order by orderbyFieldName) as row_number from table ) as rows where row_number = 1
Ankur-m
1
¡Gracias! Estaba en el mismo problema y la solución fue el GROUP BY
Joaquin Iurchuk
2
También en Oracle (Oracle SQL Developer) no puede especificar select *, row_number() over (partition by field1 order by field2) as row_number from table. select **table**.*, row_number() over (partition by field1 order by field2) as row_number from table
Debe
1
@jarlh: Podría ser ... hoy. Como puede observar, esta respuesta tiene casi 7 años, un momento en el que ese no era el caso en la medida en que puedo recordar desde que estaba activo. Puede volver a etiquetar y / o editar la respuesta si lo considera necesario.
Denis de Bernardy
2
select distinct on (field1) * from table; funciona también en PostgreSQL
Chilianu Bogdan
61
De la redacción de su pregunta, entiendo que desea seleccionar los valores distintos para un campo determinado y que cada valor tenga todos los demás valores de columna en la misma fila. La mayoría de los DBMS no permitirán esto con ni DISTINCTtampoco GROUP BY, porque el resultado no está determinado.
Piénselo de esta manera: si field1ocurre más de una vez, qué valor de field2aparecerá en la lista (dado que tiene el mismo valor field1en dos filas pero dos valores distintos de field2en esas dos filas).
Sin embargo, puede usar funciones agregadas (explícitamente para cada campo que desea que se muestren) y usar un en GROUP BYlugar de DISTINCT:
+1 para esta solución. Así que podemos hacer SELECT field1, MIN(field2), MIN(field3), MIN(field4), .... FROM table GROUP BY field1, y los campos 2, 3, 4, no están obligados a ser enteros (u otros dígitos), también pueden ser campos de caracteres
acechar el
Estaba funcionando bien hasta que me quedé atrapado en una columna booleana. Los valores de columna MIN (Dinámico) se modifican a falso incluso si era verdadero. Cualquier otra función agregada disponible para abordar boolean - signonsridhar hace 6 minutos. Suma (dinámica) cambió falso a 1
signonsridhar
1
Gran sugerencia, me llevó a mi solución, que creo que es más universal: ¡eche un vistazo!
Garrett Simpson
@signonsridhar convierte tu booleano en int y usa sum; egsum(cast(COL as int)) > 0
Drew
26
Si entendí tu problema correctamente, es similar a uno que acabo de tener. Desea poder limitar la usabilidad de DISTINCT a un campo específico, en lugar de aplicarlo a todos los datos.
Si usa GROUP BY sin una función agregada, cualquier campo que GROUP BY será su DISTINCT archivado.
Si haces tu consulta:
SELECT*fromtableGROUPBY field1;
Mostrará todos sus resultados basados en una sola instancia de field1.
Por ejemplo, si tiene una tabla con nombre, dirección y ciudad. Una sola persona tiene múltiples direcciones registradas, pero solo desea una sola dirección para la persona, puede consultar de la siguiente manera:
SELECT*FROM persons GROUPBY name;
El resultado será que solo una instancia de ese nombre aparecerá con su dirección, y la otra se omitirá de la tabla resultante. Precaución: si sus fileds tienen valores atómicos como firstName, lastName que desea agrupar por ambos.
SELECT*FROM persons GROUPBY lastName, firstName;
porque si dos personas tienen el mismo apellido y usted solo agrupa por apellido, una de esas personas será omitida de los resultados. Necesitas tener esas cosas en consideración. Espero que esto ayude.
¿Por qué hay Caliascuando puede funcionar sin él? en líneaFROM dbo.TABLE AS C
Talha
2
Creo que esto se debe a mi uso de RedGate SQLPrompt. Tal como lo configuré, siempre agrega alias, incluso si es innecesario. Está ahí "por si acaso"
Tormentoso
Esto me pareció prometedor, pero aun así recuperó todas las filas, no el campo distinto1. :(
Michael Fever
13
Esa es una muy buena pregunta. Ya he leído algunas respuestas útiles aquí, pero probablemente pueda agregar una explicación más precisa.
Reducir el número de resultados de la consulta con una instrucción GROUP BY es fácil siempre que no consulte información adicional. Supongamos que tiene la siguiente tabla 'ubicaciones'.
--country-- --city--
France Lyon
Poland Krakow
France Paris
France Marseille
Italy Milano
Ahora la consulta
SELECT country FROM locations
GROUPBY country
resultará en:
--country--
France
Poland
Italy
Sin embargo, la siguiente consulta
SELECT country, city FROM locations
GROUPBY country
... arroja un error en MS SQL, porque ¿cómo podría saber su computadora cuál de las tres ciudades francesas "Lyon", "París" o "Marsella" desea leer en el campo a la derecha de "Francia"?
Para corregir la segunda consulta, debe agregar esta información. Una forma de hacerlo es utilizar las funciones MAX () o MIN (), seleccionando el valor más grande o más pequeño entre todos los candidatos. MAX () y MIN () no solo son aplicables a valores numéricos, sino que también comparan el orden alfabético de los valores de cadena.
SELECT country, MAX(city)FROM locations
GROUPBY country
resultará en:
--country-- --city--
France Paris
Poland Krakow
Italy Milano
o:
SELECT country, MIN(city)FROM locations
GROUPBY country
resultará en:
--country-- --city--
France Lyon
Poland Krakow
Italy Milano
Estas funciones son una buena solución siempre que esté bien con la selección de su valor de los extremos del orden alfabético (o numérico). Pero, ¿y si este no es el caso? Supongamos que necesita un valor con cierta característica, por ejemplo, comenzando con la letra 'M'. Ahora las cosas se complican.
La única solución que pude encontrar hasta ahora es poner toda su consulta en una subconsulta y construir la columna adicional fuera de ella a mano:
SELECT
countrylist.*,(SELECTTOP1 city
FROM locations
WHERE
country = countrylist.country
AND city like'M%')FROM(SELECT country FROM locations
GROUPBY country) countrylist
resultará en:
--country-- --city--
France Marseille
Poland NULL
Italy Milano
Gran pregunta @aryaxt: ¡puede decir que fue una gran pregunta porque la hizo hace 5 años y hoy me topé con ella tratando de encontrar la respuesta!
Solo intenté editar la respuesta aceptada para incluir esto, pero en caso de que mi edición no se haga en:
Si su tabla no era tan grande, y suponiendo que su clave principal fuera un entero de incremento automático, podría hacer algo como esto:
SELECTtable.*FROMtable--be able to take out dupes laterLEFTJOIN(SELECT field, MAX(id)as id
FROMtableGROUPBY field
)as noDupes on noDupes.id =table.id
WHERE//this will result in only the last instance being seen
noDupes.id isnotNULL
Para SQL Server, puede usar dense_rank y las funciones adicionales de ventanas para obtener todas las filas Y columnas con valores duplicados en columnas específicas. Aquí hay un ejemplo...
with t as(select col1 ='a', col2 ='b', col3 ='c', other ='r1'unionallselect col1 ='c', col2 ='b', col3 ='a', other ='r2'unionallselect col1 ='a', col2 ='b', col3 ='c', other ='r3'unionallselect col1 ='a', col2 ='b', col3 ='c', other ='r4'unionallselect col1 ='c', col2 ='b', col3 ='a', other ='r5'unionallselect col1 ='a', col2 ='a', col3 ='a', other ='r6'), tdr as(select*,
total_dr_rows = count(*)over(partitionby dr)from(select*,
dr = dense_rank()over(orderby col1, col2, col3),
dr_rn = row_number()over(partitionby col1, col2, col3 orderby other)from
t
) x
)select*from tdr where total_dr_rows >1
Esto está tomando un recuento de filas para cada combinación distinta de col1, col2 y col3.
¡Esto funcionó para mí! Vale la pena señalar que, si está utilizando fetch_array (), deberá llamar a cada fila a través de una etiqueta de índice en lugar de llamar implícitamente el nombre de la fila. No hay suficientes caracteres en esto para que yo escriba el ejemplo que tengo: ¡X lo siento!
Como se menciona en la respuesta aceptada, funcionaría para la mayoría de las encarnaciones de SQL, solo para MYSQL
Garrett Simpson, el
0
Encontré esto en otro lugar aquí, pero esta es una solución simple que funciona:
WITH cte AS/* Declaring a new table named 'cte' to be a clone of your table */(SELECT*, ROW_NUMBER()OVER(PARTITIONBY id ORDERBY val1 DESC)AS rn
FROM MyTable /* Selecting only unique values based on the "id" field */)SELECT*/* Here you can specify several columns to retrieve */FROM cte
WHERE rn =1
La cláusula GROUP BY debe coincidir con los campos seleccionados. de lo contrario arrojará un error comofiled2 must appear in the GROUP BY clause or be used in an aggregate function
Viuu -a
-2
Simplemente incluya todos sus campos en la cláusula GROUP BY.
Esto no responde a la pregunta, el OP estaba tratando de obtener todos los datos de la tabla, pero elimina las filas que contienen duplicados de un solo campo
Garrett Simpson
-3
SELECT*fromtablewhere field in(SELECTdistinct field fromtable)
Eso no hará el trabajo. Ha seleccionado la columna distinta en la subconsulta, pero la cláusula where obtiene todas esas columnas con ese valor. Por lo tanto, la consulta es tan buena como escribir 'select * from table' a menos que la columna 'field' sea una columna única, en cuyo caso no se requiere el distintivo en esa columna.
Ankur-m
-3
SELECT DISTINCT FIELD1, FIELD2, FIELD3 FROM TABLE1 funciona si los valores de las tres columnas son únicos en la tabla.
Si, por ejemplo, tiene varios valores idénticos para el nombre, pero el apellido y otra información en las columnas seleccionadas es diferente, el registro se incluirá en el conjunto de resultados.
Esto no responde a la pregunta, el OP estaba tratando de obtener todos los datos de la tabla, pero elimina las filas que contienen duplicados de un solo campo
SELECT DISTINCT * FROM table
no funciona para ti?distinct
por definición. Si está tratando de seleccionar,DISTINCT field1
pero de alguna manera devolver todas las demás columnas, ¿qué debería suceder para aquellas columnas que tienen más de un valor para unfield1
valor en particular ? Tendría que usarGROUP BY
y algún tipo de agregación en las otras columnas, por ejemplo.Respuestas:
Estás buscando un grupo por:
Que ocasionalmente se puede escribir con una declaración distinta en:
Sin embargo, en la mayoría de las plataformas, ninguno de los anteriores funcionará porque el comportamiento en las otras columnas no está especificado. (El primero funciona en MySQL, si eso es lo que está usando).
Puede buscar los distintos campos y seguir eligiendo una sola fila arbitraria cada vez.
En algunas plataformas (por ejemplo, PostgreSQL, Oracle, T-SQL), esto se puede hacer directamente usando funciones de ventana:
En otros (MySQL, SQLite), necesitará escribir subconsultas que lo harán unir toda la tabla consigo mismo ( ejemplo ), por lo que no es recomendable.
fuente
The ranking function "row_number" must have an ORDER BY clause
. Necesitamos agregar orden por cláusula después de la partición por campo1. Entonces la consulta correcta seráselect * from ( select *, row_number() over (partition by field1 order by orderbyFieldName) as row_number from table ) as rows where row_number = 1
GROUP BY
select *, row_number() over (partition by field1 order by field2) as row_number from table
.select **table**.*, row_number() over (partition by field1 order by field2) as row_number from table
select distinct on (field1) * from table
; funciona también en PostgreSQLDe la redacción de su pregunta, entiendo que desea seleccionar los valores distintos para un campo determinado y que cada valor tenga todos los demás valores de columna en la misma fila. La mayoría de los DBMS no permitirán esto con ni
DISTINCT
tampocoGROUP BY
, porque el resultado no está determinado.Piénselo de esta manera: si
field1
ocurre más de una vez, qué valor defield2
aparecerá en la lista (dado que tiene el mismo valorfield1
en dos filas pero dos valores distintos defield2
en esas dos filas).Sin embargo, puede usar funciones agregadas (explícitamente para cada campo que desea que se muestren) y usar un en
GROUP BY
lugar deDISTINCT
:fuente
SELECT field1, MIN(field2), MIN(field3), MIN(field4), .... FROM table GROUP BY field1
, y los campos 2, 3, 4, no están obligados a ser enteros (u otros dígitos), también pueden ser campos de caracteressum(cast(COL as int)) > 0
Si entendí tu problema correctamente, es similar a uno que acabo de tener. Desea poder limitar la usabilidad de DISTINCT a un campo específico, en lugar de aplicarlo a todos los datos.
Si usa GROUP BY sin una función agregada, cualquier campo que GROUP BY será su DISTINCT archivado.
Si haces tu consulta:
Mostrará todos sus resultados basados en una sola instancia de field1.
Por ejemplo, si tiene una tabla con nombre, dirección y ciudad. Una sola persona tiene múltiples direcciones registradas, pero solo desea una sola dirección para la persona, puede consultar de la siguiente manera:
El resultado será que solo una instancia de ese nombre aparecerá con su dirección, y la otra se omitirá de la tabla resultante. Precaución: si sus fileds tienen valores atómicos como firstName, lastName que desea agrupar por ambos.
porque si dos personas tienen el mismo apellido y usted solo agrupa por apellido, una de esas personas será omitida de los resultados. Necesitas tener esas cosas en consideración. Espero que esto ayude.
fuente
fuente
C
alias
cuando puede funcionar sin él? en líneaFROM dbo.TABLE AS C
Esa es una muy buena pregunta. Ya he leído algunas respuestas útiles aquí, pero probablemente pueda agregar una explicación más precisa.
Reducir el número de resultados de la consulta con una instrucción GROUP BY es fácil siempre que no consulte información adicional. Supongamos que tiene la siguiente tabla 'ubicaciones'.
Ahora la consulta
resultará en:
Sin embargo, la siguiente consulta
... arroja un error en MS SQL, porque ¿cómo podría saber su computadora cuál de las tres ciudades francesas "Lyon", "París" o "Marsella" desea leer en el campo a la derecha de "Francia"?
Para corregir la segunda consulta, debe agregar esta información. Una forma de hacerlo es utilizar las funciones MAX () o MIN (), seleccionando el valor más grande o más pequeño entre todos los candidatos. MAX () y MIN () no solo son aplicables a valores numéricos, sino que también comparan el orden alfabético de los valores de cadena.
resultará en:
o:
resultará en:
Estas funciones son una buena solución siempre que esté bien con la selección de su valor de los extremos del orden alfabético (o numérico). Pero, ¿y si este no es el caso? Supongamos que necesita un valor con cierta característica, por ejemplo, comenzando con la letra 'M'. Ahora las cosas se complican.
La única solución que pude encontrar hasta ahora es poner toda su consulta en una subconsulta y construir la columna adicional fuera de ella a mano:
resultará en:
fuente
Gran pregunta @aryaxt: ¡puede decir que fue una gran pregunta porque la hizo hace 5 años y hoy me topé con ella tratando de encontrar la respuesta!
Solo intenté editar la respuesta aceptada para incluir esto, pero en caso de que mi edición no se haga en:
Si su tabla no era tan grande, y suponiendo que su clave principal fuera un entero de incremento automático, podría hacer algo como esto:
fuente
Tratar
fuente
Puedes hacerlo con una
WITH
cláusula.Por ejemplo:
Esto también le permite seleccionar solo las filas seleccionadas en la
WITH
consulta de cláusulas.fuente
Para SQL Server, puede usar dense_rank y las funciones adicionales de ventanas para obtener todas las filas Y columnas con valores duplicados en columnas específicas. Aquí hay un ejemplo...
Esto está tomando un recuento de filas para cada combinación distinta de col1, col2 y col3.
fuente
fuente
en
ORDER BY
acabo de poner un ejemplo aquí, también puede agregar el campo ID en estefuente
Encontré esto en otro lugar aquí, pero esta es una solución simple que funciona:
fuente
Agregue GROUP BY al campo en el que desea verificar si hay duplicados en su consulta.
el campo 1 se verificará para excluir registros duplicados
o puede consultar como
los registros duplicados del campo 1 se excluyen de SELECCIONAR
fuente
filed2 must appear in the GROUP BY clause or be used in an aggregate function
Simplemente incluya todos sus campos en la cláusula GROUP BY.
fuente
Se puede hacer por consulta interna
fuente
fuente
SELECT DISTINCT FIELD1, FIELD2, FIELD3 FROM TABLE1 funciona si los valores de las tres columnas son únicos en la tabla.
Si, por ejemplo, tiene varios valores idénticos para el nombre, pero el apellido y otra información en las columnas seleccionadas es diferente, el registro se incluirá en el conjunto de resultados.
fuente
Sugeriría usar
de esta manera, si tiene el mismo valor en el campo 1 en varias filas, se devolverán todos los registros.
fuente
SELECT * FROM table;
. Aún más es lento.