SQL / mysql-choisir distinct / UNIQUE mais retourner toutes les colonnes?
SELECT DISTINCT field1, field2, field3, ...... FROM table
j'essaie d'accomplir la déclaration sql suivante mais je veux qu'elle retourne toutes les colonnes est-ce possible? Quelque chose comme:
SELECT DISTINCT field1, * from table
15 réponses
vous recherchez un groupe par:
select *
from table
group by field1
qui peut parfois être écrit avec un distinct sur la déclaration:
select distinct on field1 *
from table
sur la plupart des plates-formes, cependant, aucun des deux ci-dessus ne fonctionnera parce que le comportement sur les autres colonnes est indéterminée. (Le premier fonctionne avec MySQL, si c'est ce que vous êtes en utilisant.)
vous pourriez aller chercher les champs distincts et vous en tenir à choisir une seule rangée arbitraire à chaque fois.
sur certaines plateformes (par exemple PostgreSQL, Oracle, T-SQL) cela peut être fait directement en utilisant les fonctions de fenêtre:
select *
from (
select *,
row_number() over (partition by field1 order by field2) as row_number
from table
) as rows
where row_number = 1
sur d'autres (MySQL, SQLite), vous aurez besoin d'écrire des sous-séries qui vous feront rejoindre la table entière avec lui-même ( exemple ), donc pas recommandé.
D'après le libellé de votre question, je comprends que vous voulez sélectionner les valeurs distinctes pour un champ donné et pour chacune de ces valeurs d'avoir toutes les autres valeurs de colonne dans la même rangée énumérée. La plupart des DBMSs ne le permettent pas avec ni DISTINCT
ni GROUP BY
, parce que le résultat n'est pas déterminé.
pensez à cela comme ceci: si votre field1
se produit plus d'une fois, quelle valeur de field2
sera listée (étant donné que vous avez la même valeur pour field1
en deux lignes, mais deux valeurs distinctes de field2
dans ces deux lignes).
vous pouvez cependant utiliser des fonctions agrégées (explicitement pour chaque champ que vous voulez afficher) et en utilisant un GROUP BY
au lieu de DISTINCT
:
SELECT field1, MAX(field2), COUNT(field3), SUM(field4), .... FROM table GROUP BY field1
si j'ai bien compris votre problème, il est similaire à celui que je viens d'avoir. Vous voulez être en mesure de limiter L'utilisabilité de DISTINCT à un champ spécifié, plutôt que de l'appliquer à toutes les données.
si vous utilisez GROUP BY sans une fonction agrégée, quel que soit le champ que vous groupez, ce sera votre dépôt DISTINCT.
si vous faites votre requête:
SELECT * from table GROUP BY field1;
il affichera tous vos résultats basés sur une seule instance de champ1.
Par exemple, si vous avez une table avec le nom, l'adresse et la ville. Une seule personne a plusieurs adresses enregistrées, mais vous voulez juste une adresse unique pour la personne, vous pouvez requête comme suit:
SELECT * FROM persons GROUP BY name;
Le résultat sera qu'une seule instance de ce nom apparaîtra avec son adresse, et l'autre sera omis dans le tableau résultant. Attention: si vos fichiers ont des valeurs atomiques telles que firstName, lastName, vous voulez les grouper par les deux.
SELECT * FROM persons GROUP BY lastName, firstName;
parce que si deux personnes ont le même nom de famille et que vous ne groupez que par lastName, une de ces personnes sera omise des résultats. Vous devez garder ces choses en considération. Espérons que cette aide.
SELECT c2.field1 ,
field2
FROM (SELECT DISTINCT
field1
FROM dbo.TABLE AS C
) AS c1
JOIN dbo.TABLE AS c2 ON c1.field1 = c2.field1
C'est une très bonne question. J'ai déjà lu quelques réponses utiles, mais je peux probablement ajouter une explication plus précise.
réduire le nombre de résultats de requête avec un groupe par l'énoncé est facile Aussi longtemps que vous n'interrogez pas l'information supplémentaire. Supposons que vous ayez le tableau suivant "emplacements".
--country-- --city--
France Lyon
Poland Krakow
France Paris
France Marseille
Italy Milano
Maintenant, la requête
SELECT country FROM locations
GROUP BY country
résultera en:
--country--
France
Poland
Italy
cependant, la requête suivante
SELECT country, city FROM locations
GROUP BY country
...une erreur dans MS SQL, car comment votre ordinateur pourrait-il savoir laquelle des trois villes françaises "Lyon", "Paris" ou "Marseille" vous voulez lire sur le terrain à droite de "France"?
afin de corriger la deuxième requête, vous devez ajouter cette information. Une façon de le faire est d'utiliser les fonctions MAX() ou MIN(), en sélectionnant la plus grande ou la plus petite valeur parmi tous les candidats. MAX() et MIN () ne sont pas seulement applicables aux valeurs numériques, mais aussi comparer l'ordre alphabétique des valeurs de chaîne.
SELECT country, MAX(city) FROM locations
GROUP BY country
résultera en:
--country-- --city--
France Paris
Poland Krakow
Italy Milano
ou:
SELECT country, MIN(city) FROM locations
GROUP BY country
résultera en:
--country-- --city--
France Lyon
Poland Krakow
Italy Milano
ces fonctions sont une bonne solution tant que vous êtes d'accord avec la sélection de votre valeur à partir des deux extrémités de l'ordre alphabétique (ou numérique). Mais que faire si ce n'est pas le cas? Supposons que vous ayez besoin d'une valeur avec une certaine caractéristique, par exemple en commençant par la lettre "M". Maintenant, les choses se compliquent.
la seule solution que j'ai pu trouver jusqu'à présent est de mettre toute votre requête dans un sous-jeu, et de construire la colonne supplémentaire à l'extérieur de celui-ci par les mains:
SELECT
countrylist.*,
(SELECT TOP 1 city
FROM locations
WHERE
country = countrylist.country
AND city like 'M%'
)
FROM
(SELECT country FROM locations
GROUP BY country) countrylist
résultera en:
--country-- --city--
France Marseille
Poland NULL
Italy Milano
grande question @aryaxt -- vous pouvez dire que c'était une grande question parce que vous l'avez posée il y a 5 ans et je suis tombé sur elle aujourd'hui en essayant de trouver la réponse!
j'ai juste essayé d'éditer la réponse acceptée pour inclure ceci, mais au cas où mon édition ne le fait pas dans:
si votre table n'était pas si grande, et en supposant que votre clé primaire était un entier auto-incrémentant vous pourriez faire quelque chose comme ceci:
SELECT
table.*
FROM table
--be able to take out dupes later
LEFT JOIN (
SELECT field, MAX(id) as id
FROM table
GROUP BY field
) as noDupes on noDupes.id = table.id
WHERE
//this will result in only the last instance being seen
noDupes.id is not NULL
vous pouvez le faire avec une clause WITH
.
par exemple:
WITH c AS (SELECT DISTINCT a, b, c FROM tableName)
SELECT * FROM tableName r, c WHERE c.rowid=r.rowid AND c.a=r.a AND c.b=r.b AND c.c=r.c
cela vous permet également de sélectionner uniquement les lignes sélectionnées dans la requête WITH
.
pour SQL Server vous pouvez utiliser les fonctions dense_rank et windowing supplémentaires pour obtenir toutes les lignes et les colonnes avec des valeurs dupliquées sur les colonnes spécifiées. Ici est un exemple...
with t as (
select col1 = 'a', col2 = 'b', col3 = 'c', other = 'r1' union all
select col1 = 'c', col2 = 'b', col3 = 'a', other = 'r2' union all
select col1 = 'a', col2 = 'b', col3 = 'c', other = 'r3' union all
select col1 = 'a', col2 = 'b', col3 = 'c', other = 'r4' union all
select col1 = 'c', col2 = 'b', col3 = 'a', other = 'r5' union all
select col1 = 'a', col2 = 'a', col3 = 'a', other = 'r6'
), tdr as (
select
*,
total_dr_rows = count(*) over(partition by dr)
from (
select
*,
dr = dense_rank() over(order by col1, col2, col3),
dr_rn = row_number() over(partition by col1, col2, col3 order by other)
from
t
) x
)
select * from tdr where total_dr_rows > 1
cela prend un nombre de lignes pour chaque combinaison distincte de col1, col2 et col3.
SELECT *
FROM tblname
GROUP BY duplicate_values
ORDER BY ex.VISITED_ON DESC
LIMIT 0 , 30
dans ORDER BY
je viens de mettre l'exemple ici, vous pouvez aussi ajouter le champ ID dans ce
Ajouter groupe par au champ que vous voulez vérifier pour les doublons votre requête peut ressembler à
SELECT field1, field2, field3, ...... FROM table GROUP BY field1
la Zone 1 sera cochée pour exclure les enregistrements en double
ou vous pouvez interroger comme
SELECT * FROM table GROUP BY field1
les enregistrements en double du Champ 1 sont exclus de SELECT
je suggérerais d'utiliser
SELECT * from table where field1 in
(
select distinct field1 from table
)
de cette façon, si vous avez la même valeur dans champ1 sur plusieurs lignes, tous les dossiers seront retournés.
Il peut être fait par requête interne
$query = "SELECT *
FROM (SELECT field
FROM table
ORDER BY id DESC) as rows
GROUP BY field";
SELECT * from table where field in (SELECT distinct field from table)
sélectionnez le champ DISTINCT 1, LE CHAMP 2, le champ 3 du tableau 1 si les valeurs des trois colonnes sont uniques dans le tableau.
Si, par exemple, vous avez plusieurs valeurs identiques pour le prénom, mais le nom de famille et d'autres informations dans les colonnes sélectionnées est différent, l'enregistrement sera inclus dans le jeu de résultats.