DISTINCT pour une seule colonne

Disons que j'ai la requête suivante.

SELECT ID, Email, ProductName, ProductModel FROM Products

Comment puis-je le modifier pour qu'il ne renvoie aucun e-mail en double?

En d'autres termes, lorsque plusieurs lignes contiennent le même email, je veux que les résultats n'incluent qu'une seule de ces lignes (de préférence la dernière). Les doublons dans d'autres colonnes devraient être autorisés.

Clauses comme DISTINCT et GROUP BY semblent fonctionner sur des lignes entières. Donc, je ne suis pas sûr de savoir comment aborder cela.

123
demandé sur Jonathan Wood 2011-02-16 23:23:19

7 réponses

Si vous utilisez SQL Server 2005 ou supérieur, utilisez ceci:

SELECT *
  FROM (
                SELECT  ID, 
                        Email, 
                        ProductName, 
                        ProductModel,
                        ROW_NUMBER() OVER(PARTITION BY Email ORDER BY ID DESC) rn
                    FROM Products
              ) a
WHERE rn = 1

Modifier: Exemple utilisant une clause where:

SELECT *
  FROM (
                SELECT  ID, 
                        Email, 
                        ProductName, 
                        ProductModel,
                        ROW_NUMBER() OVER(PARTITION BY Email ORDER BY ID DESC) rn
                    FROM Products
                   WHERE ProductModel = 2
                     AND ProductName LIKE 'CYBER%'

              ) a
WHERE rn = 1
140
répondu Chandu 2011-02-16 22:05:37

Cela suppose SQL Server 2005+ et votre définition de "last" est le PK maximum pour un e-mail donné

;WITH CTE AS
(
SELECT ID, 
       Email, 
       ProductName, 
       ProductModel, 
       ROW_NUMBER() OVER (PARTITION BY Email ORDER BY ID DESC) AS RowNumber 
FROM   Products
)
SELECT ID, 
       Email, 
       ProductName, 
       ProductModel
FROM CTE 
WHERE RowNumber = 1
9
répondu Pero P. 2011-02-16 20:40:23

Lorsque vous utilisez DISTINCT pensez-y comme une ligne distincte, pas une colonne. Il ne retournera que les lignes où les colonnes ne correspondent pas exactement à la même chose.

SELECT DISTINCT ID, Email, ProductName, ProductModel
FROM Products

----------------------
1 | something@something.com | ProductName1 | ProductModel1
2 | something@something.com | ProductName1 | ProductModel1

La requête retournerait les deux lignes car la colonne ID est différente. Je suppose que la colonne ID est une colonne IDENTITY qui s'incrémente, si vous voulez retourner la dernière, je recommande quelque chose comme ceci:

SELECT DISTINCT TOP 1 ID, Email, ProductName, ProductModel
FROM Products
ORDER BY ID DESC

Le TOP 1 renverra seulement le premier enregistrement, en l'ordonnant par le ID décroissant il renverra le résultats avec la dernière ligne en premier. Cela vous donnera le dernier enregistrement.

5
répondu jon3laze 2011-02-16 20:33:51

Vous pouvez sur cela en utilisant GROUP BY function

SELECT ID, Email, ProductName, ProductModel FROM Products GROUP BY Email
4
répondu Marshall Unduemi 2016-02-21 23:56:47

Pour L'accès, vous pouvez utiliser la requête SQL Select que je présente ici:

Par exemple, vous avez ce tableau:

CLIENTE || NOMBRES / / MAIL

888 || T800 ARNOLD / / t800.arnold@cyberdyne.com

123 || JOHN CONNOR / / s.connor@skynet.com

125 ||SARAH CONNOR / / s.connor@skynet.com

Et vous devez sélectionner uniquement des mails distincts. Vous pouvez le faire avec ceci:

SQL SELECT:

SELECT MAX(p.CLIENTE) AS ID_CLIENTE
, (SELECT TOP 1 x.NOMBRES 
    FROM Rep_Pre_Ene_MUESTRA AS x 
    WHERE x.MAIL=p.MAIL 
     AND x.CLIENTE=(SELECT MAX(l.CLIENTE) FROM Rep_Pre_Ene_MUESTRA AS l WHERE x.MAIL=l.MAIL)) AS NOMBRE, 
p.MAIL
FROM Rep_Pre_Ene_MUESTRA AS p
GROUP BY p.MAIL;

Vous pouvez l'utiliser pour sélectionner nom correspondant à cet ID maximum, vous pouvez ajouter n'importe quel autre attribut de cette façon. Ensuite, à la fin, vous mettez la colonne distincte à filtrer et vous ne le groupez qu'avec cette dernière colonne distincte.

Cela vous apportera l'ID maximum avec les données correspondantes, vous pouvez utiliser min ou d'autres fonctions et vous répliquez cette fonction aux sous-requêtes.

Cette sélection renverra:

CLIENTE || NOMBRES / / MAIL

888 ||T800 ARNOLD / / t800.arnold@cyberdyne.com

125 ||SARAH CONNOR / / s.connor@skynet.com

N'oubliez pas d'indexer les colonnes que vous sélectionnez et la colonne distincte ne doit pas avoir de données numériques toutes en majuscules ou en minuscules, sinon cela ne fonctionnera pas. Cela fonctionne avec un seul courrier recommandé ainsi. Amusez-vous bien!!!

0
répondu jRam90 2013-01-30 15:10:04

Essayez Ceci

;With Tab AS (SELECT DISTINCT Email FROM  Products)
SELECT Email,ROW_NUMBER() OVER(ORDER BY Email ASC) AS  Id FROM Tab
ORDER BY Email ASC
0
répondu Abdullah Yousuf 2017-02-19 06:25:22

La raison pour laquelle DISTINCT et GROUP BY fonctionnent sur des lignes entières est que votre requête renvoie des lignes entières.

Pour vous aider à comprendre: essayez d'écrire à la main ce que la requête doit retourner et vous verrez qu'il est ambigu ce qu'il faut mettre dans les colonnes non dupliquées.

Si vous ne vous souciez littéralement pas de ce qui est dans les autres colonnes, ne les retournez pas. Retourner une ligne aléatoire pour chaque adresse e-mail me semble un peu inutile.

-1
répondu JohnFx 2015-09-22 14:49:50