SELECT DISTINCT field1, field2, field3, ...... FROM table
J'essaie d'accomplir l'instruction SQL suivante, mais je souhaite qu'elle renvoie toutes les colonnes. Est-ce possible? Quelque chose comme:
SELECT DISTINCT field1, * from table
Vous recherchez un groupe par:
select *
from table
group by field1
Ce qui peut parfois être écrit avec une déclaration distincte:
select distinct on field1 *
from table
Sur la plupart des plates-formes, cependant, aucune des solutions ci-dessus ne fonctionnera, car le comportement des autres colonnes n'est pas spécifié. (Le premier fonctionne sous MySQL, si c'est ce que vous utilisez.)
Vous pouvez aller chercher les champs distincts et vous en tenir à choisir une seule ligne arbitraire à chaque fois.
Sur certaines plates-formes (telles que PostgreSQL, Oracle, T-SQL), cela peut être fait directement à l'aide de 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 devrez écrire des sous-requêtes qui vous obligeront à joindre la table entière à elle-même ( exemple ), ce qui n’est pas recommandé.
D'après le libellé de votre question, je comprends que vous souhaitez sélectionner les valeurs distinctes pour un champ donné et que pour chacune d'elles, toutes les autres valeurs de colonne de la même ligne soient répertoriées. La plupart des SGBD ne le permettent pas avec ni DISTINCT
ni GROUP BY
, car le résultat n'est pas déterminé.
Pensez-y comme ceci: si votre field1
apparaît plusieurs fois, quelle valeur de field2
sera listée (étant donné que vous avez la même valeur pour field1
sur deux lignes mais deux valeurs distinctes de field2
dans ces deux lignes).
Vous pouvez cependant utiliser des fonctions d'agrégat (explicitement pour chaque champ à afficher) et utiliser 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, c'est semblable à celui que je viens d'avoir. Vous voulez pouvoir 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 d'agrégat, quel que soit le champ, GROUP BY sera votre fichier DISTINCT.
Si vous faites votre requête:
SELECT * from table GROUP BY field1;
Il montrera tous vos résultats basés sur une seule instance de field1.
Par exemple, si vous avez une table avec nom, adresse et ville. Une seule personne a plusieurs adresses enregistrées, mais vous voulez juste une seule adresse pour la personne, vous pouvez interroger 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 que l'autre sera omise de la table résultante. Attention: si vos champs ont des valeurs atomiques telles que firstName, lastName que vous souhaitez 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 regroupez que par nom, l'une de ces personnes sera omise des résultats. Vous devez garder ces choses en considération. J'espère que cela t'aides.
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 la requête avec une instruction GROUP BY est simple si vous ne demandez pas d'informations supplémentaires. 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
aura pour résultat:
--country--
France
Poland
Italy
Cependant, la requête suivante
SELECT country, city FROM locations
GROUP BY country
... génère une erreur dans MS SQL, car comment votre ordinateur peut-il savoir laquelle des trois villes françaises "Lyon", "Paris" ou "Marseille" vous souhaitez lire dans le champ situé à droite de "France"?
Afin de corriger la deuxième requête, vous devez ajouter cette information. Une façon de faire est d'utiliser les fonctions MAX () ou MIN (), en sélectionnant la valeur la plus grande ou la plus petite parmi tous les candidats. MAX () et MIN () s'appliquent non seulement aux valeurs numériques, mais comparent également l'ordre alphabétique des valeurs de chaîne.
SELECT country, MAX(city) FROM locations
GROUP BY country
aura pour résultat:
--country-- --city--
France Paris
Poland Krakow
Italy Milano
ou:
SELECT country, MIN(city) FROM locations
GROUP BY country
aura pour résultat:
--country-- --city--
France Lyon
Poland Krakow
Italy Milano
Ces fonctions sont une bonne solution tant que vous pouvez sélectionner votre valeur à l’une ou l’autre des extrémités de l’ordre alphabétique (ou numérique). Mais si ce n'est pas le cas? Supposons qu'il vous faut 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 placer votre requête entière dans une sous-requête et de construire la colonne supplémentaire à l'extérieur de celle-ci:
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
aura pour résultat:
--country-- --city--
France Marseille
Poland NULL
Italy Milano
Excellente question @aryaxt - vous pouvez dire que c’était une excellente question parce que vous l’aviez posée il ya 5 ans et que je suis tombé sur elle aujourd’hui en essayant de trouver la réponse!
Je viens d'essayer de modifier la réponse acceptée pour inclure ceci, mais au cas où ma modification ne le ferait pas:
Si votre table n'était pas si grande, et en supposant que votre clé primaire était un entier auto-incrémenté, vous pourriez faire quelque chose comme ça:
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 de clauses WITH
.
Pour SQL Server, vous pouvez utiliser les fonctions dense_rank et Windows supplémentaires pour obtenir toutes les lignes ET les colonnes avec des valeurs dupliquées sur des colonnes spécifiées. Voici 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.
Essayer
SELECT table.* FROM table
WHERE otherField = 'otherValue'
GROUP BY table.fieldWantedToBeDistinct
limit x
SELECT *
FROM tblname
GROUP BY duplicate_values
ORDER BY ex.VISITED_ON DESC
LIMIT 0 , 30
dans ORDER BY
je viens de mettre exemple ici, vous pouvez également ajouter un champ ID dans cette