Sqlserver
 sql >> Datenbank >  >> RDS >> Sqlserver

Duplikate aus Komma- oder Pipeline-Operatorzeichenfolge entfernen

Ansatz

Der folgende Ansatz kann verwendet werden, um eine begrenzte Werteliste zu deduplizieren.

  1. Verwenden Sie REPLACE() Funktion, um verschiedene Trennzeichen in dasselbe Trennzeichen umzuwandeln.
  2. Verwenden Sie REPLACE() Funktion zum Einfügen von schließenden und öffnenden XML-Tags, um ein XML-Fragment zu erstellen
  3. Verwenden Sie den CAST(expr AS XML) Funktion, um das obige Fragment in den XML-Datentyp
  4. zu konvertieren
  5. Verwenden Sie OUTER APPLY um die Tabellenwertfunktion nodes() anzuwenden um das XML-Fragment in seine einzelnen XML-Tags aufzuteilen. Dadurch wird jedes XML-Tag in einer separaten Zeile zurückgegeben.
  6. Extrahieren Sie mithilfe von value() nur den Wert aus dem XML-Tag -Funktion und gibt den Wert mit dem angegebenen Datentyp zurück.
  7. Hängen Sie nach dem oben genannten Wert ein Komma an.
  8. Beachten Sie, dass diese Werte in separaten Zeilen zurückgegeben werden. Die Verwendung des DISTINCT Schlüsselwort entfernt jetzt doppelte Zeilen (d. h. Werte).
  9. Verwenden Sie den FOR XML PATH('') -Klausel, um die Werte über mehrere Zeilen hinweg zu einer einzigen Zeile zu verketten.

Abfrage

Setzen Sie den obigen Ansatz in Abfrageform:

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('') 

Eingabe &Ergebnis

Angesichts der Eingabe:

Die obige Abfrage gibt das Ergebnis zurück:

Beachten Sie das abschließende Komma am Ende. Ich überlasse es Ihnen als Übung, das zu entfernen.

BEARBEITEN:Anzahl der Duplikate

OP in einem Kommentar angefordert "wie bekomme ich auch die Anzahl der Duplikate? in einer separaten Spalte ".

Der einfachste Weg wäre, die obige Abfrage zu verwenden, aber die letzte Zeile FOR XML PATH('') zu entfernen . Zählen Sie dann alle Werte und eindeutigen Werte, die von SELECT zurückgegeben werden Ausdruck in der obigen Abfrage (z. B. PivotedTable.PivotedColumn.value('.','nvarchar(max)') ). Die Differenz zwischen der Anzahl aller Werte und der Anzahl unterschiedlicher Werte ist die Anzahl der doppelten Werte.

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) 

Für die oben gezeigte Eingabe lautet die Ausgabe dieser Abfrage:

CountOfAllValues CountOfUniqueValues CountOfDuplicateValues
---------------- ------------------- ----------------------
8                4                   4