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.
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
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
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.
Vous pouvez sur cela en utilisant GROUP BY function
SELECT ID, Email, ProductName, ProductModel FROM Products GROUP BY Email
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!!!
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
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.