sql >> Databasteknik >  >> RDS >> Sqlserver

ta bort dubbletter från komma- eller pipelineoperatörssträng

Tillvägagångssätt

Följande tillvägagångssätt kan användas för att deduplicera en avgränsad lista med värden.

  1. Använd REPLACE() funktion för att konvertera olika avgränsare till samma avgränsare.
  2. Använd REPLACE() funktion för att injicera XML-stängnings- och öppningstaggar för att skapa ett XML-fragment
  3. Använd CAST(expr AS XML) funktion för att konvertera ovanstående fragment till XML-datatypen
  4. Använd OUTER APPLY för att tillämpa den tabellvärdade funktionen nodes() för att dela upp XML-fragmentet i dess ingående XML-taggar. Detta returnerar varje XML-tagg på en separat rad.
  5. Extrahera bara värdet från XML-taggen med value() funktion och returnerar värdet med den angivna datatypen.
  6. Lägg till ett kommatecken efter det ovan nämnda värdet.
  7. Observera att dessa värden returneras på separata rader. Användningen av DISTINCT nyckelordet tar nu bort dubbletter av rader (dvs värden).
  8. Använd FOR XML PATH('') sats för att sammanfoga värdena över flera rader till en enda rad.

Fråga

Att sätta ovanstående tillvägagångssätt i frågeform:

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

Indata och resultat

Med tanke på inmatningen:

Ovanstående fråga kommer att returnera resultatet:

Lägg märke till det avslutande kommatecken i slutet. Jag lämnar det som en övning till dig att ta bort det.

EDIT:Antal dubbletter

OP begärde i en kommentar "hur får jag även antalet dubbletter? i en separat kolumn ".

Det enklaste sättet skulle vara att använda ovanstående fråga men ta bort den sista raden FOR XML PATH('') . Räknar sedan alla värden och distinkta värden som returneras av SELECT uttryck i ovanstående fråga (dvs. PivotedTable.PivotedColumn.value('.','nvarchar(max)') ). Skillnaden mellan antalet av alla värden och antalet distinkta värden är antalet dubbletter av värden.

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 samma indata som visas ovan är utdata från denna fråga:

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


  1. SQL Server 2008 Anslutningsfel Ingen process finns i andra änden av röret

  2. Doktrinen består inte entitet med booleska värden och PDO::ATTR_EMULATE_PREPARES =false i Mysql

  3. Konvertera 'datetime' till 'smalldatetime' i SQL Server (T-SQL-exempel)

  4. PostgreSQL användarbehörigheter