Approche
L'approche suivante peut être utilisée pour dédupliquer une liste délimitée de valeurs.
- Utilisez le
REPLACE()
fonction pour convertir différents délimiteurs en le même délimiteur. - Utilisez le
REPLACE()
fonction pour injecter des balises de fermeture et d'ouverture XML pour créer un fragment XML - Utilisez le
CAST(expr AS XML)
fonction pour convertir le fragment ci-dessus dans le type de données XML - Utilisez
OUTER APPLY
pour appliquer la fonction tablenodes()
pour diviser le fragment XML en ses balises XML constitutives. Cela renvoie chaque balise XML sur une ligne distincte. - Extraire uniquement la valeur de la balise XML à l'aide de
value()
fonction et renvoie la valeur en utilisant le type de données spécifié. - Ajoutez une virgule après la valeur mentionnée ci-dessus.
- Notez que ces valeurs sont renvoyées sur des lignes distinctes. L'utilisation du
DISTINCT
le mot-clé supprime désormais les lignes en double (c'est-à-dire les valeurs). - Utilisez le
FOR XML PATH('')
clause pour concaténer les valeurs sur plusieurs lignes en une seule ligne.
Requête
Mettre l'approche ci-dessus sous forme de requête :
SELECT DISTINCT PivotedTable.PivotedColumn.value('.','nvarchar(max)') + ','
FROM (
-- This query returns the following in theDataXml column:
-- <tag>test1</tag><tag>test2</tag><tag>test1</tag><tag>test2</tag><tag>test3</tag><tag>test4</tag><tag>test4</tag><tag>test4</tag>
-- i.e. it has turned the original delimited data into an XML fragment
SELECT
DataTable.DataColumn AS DataRaw
, CAST(
'<tag>'
-- First replace commas with pipes to have only a single delimiter
-- Then replace the pipe delimiters with a closing and opening tag
+ replace(replace(DataTable.DataColumn, ',','|'), '|','</tag><tag>')
-- Add a final set of closing tags
+ '</tag>'
AS XML) AS DataXml
FROM ( SELECT 'test1,test2,test1|test2,test3|test4,test4|test4' AS DataColumn) AS DataTable
) AS x
OUTER APPLY DataXml.nodes('tag') AS PivotedTable(PivotedColumn)
-- Running the query without the following line will return the data in separate rows
-- Running the query with the following line returns the rows concatenated, i.e. it returns:
-- test1,test2,test3,test4,
FOR XML PATH('')
Entrée et résultat
Étant donné l'entrée :
La requête ci-dessus renverra le résultat :
Remarquez la virgule finale à la fin. Je vais vous laisser un exercice pour supprimer cela.
EDIT :Nombre de doublons
OP a demandé dans un commentaire "comment puis-je également obtenir le nombre de doublons ? dans une colonne séparée ".
Le moyen le plus simple serait d'utiliser la requête ci-dessus mais de supprimer la dernière ligne FOR XML PATH('')
. Ensuite, en comptant toutes les valeurs et les valeurs distinctes renvoyées par le SELECT
expression dans la requête ci-dessus (c'est-à-dire PivotedTable.PivotedColumn.value('.','nvarchar(max)')
). La différence entre le nombre de toutes les valeurs et le nombre de valeurs distinctes correspond au nombre de valeurs en double.
SELECT
COUNT(PivotedTable.PivotedColumn.value('.','nvarchar(max)')) AS CountOfAllValues
, COUNT(DISTINCT PivotedTable.PivotedColumn.value('.','nvarchar(max)')) AS CountOfUniqueValues
-- The difference of the previous two counts is the number of duplicate values
, COUNT(PivotedTable.PivotedColumn.value('.','nvarchar(max)'))
- COUNT(DISTINCT PivotedTable.PivotedColumn.value('.','nvarchar(max)')) AS CountOfDuplicateValues
FROM (
-- This query returns the following in theDataXml column:
-- <tag>test1</tag><tag>test2</tag><tag>test1</tag><tag>test2</tag><tag>test3</tag><tag>test4</tag><tag>test4</tag><tag>test4</tag>
-- i.e. it has turned the original delimited data into an XML fragment
SELECT
DataTable.DataColumn AS DataRaw
, CAST(
'<tag>'
-- First replace commas with pipes to have only a single delimiter
-- Then replace the pipe delimiters with a closing and opening tag
+ replace(replace(DataTable.DataColumn, ',','|'), '|','</tag><tag>')
-- Add a final set of closing tags
+ '</tag>'
AS XML) AS DataXml
FROM ( SELECT 'test1,test2,test1|test2,test3|test4,test4|test4' AS DataColumn) AS DataTable
) AS x
OUTER APPLY DataXml.nodes('tag') AS PivotedTable(PivotedColumn)
Pour la même entrée montrée ci-dessus, la sortie de cette requête est :
CountOfAllValues CountOfUniqueValues CountOfDuplicateValues
---------------- ------------------- ----------------------
8 4 4