Sqlserver
 sql >> Base de données >  >> RDS >> Sqlserver

supprimer les doublons de la virgule ou de la chaîne d'opérateur de pipeline

Approche

L'approche suivante peut être utilisée pour dédupliquer une liste délimitée de valeurs.

  1. Utilisez le REPLACE() fonction pour convertir différents délimiteurs en le même délimiteur.
  2. Utilisez le REPLACE() fonction pour injecter des balises de fermeture et d'ouverture XML pour créer un fragment XML
  3. Utilisez le CAST(expr AS XML) fonction pour convertir le fragment ci-dessus dans le type de données XML
  4. Utilisez OUTER APPLY pour appliquer la fonction table nodes() pour diviser le fragment XML en ses balises XML constitutives. Cela renvoie chaque balise XML sur une ligne distincte.
  5. 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é.
  6. Ajoutez une virgule après la valeur mentionnée ci-dessus.
  7. 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).
  8. 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