Tillvägagångssätt
Följande tillvägagångssätt kan användas för att deduplicera en avgränsad lista med värden.
- Använd
REPLACE()
funktion för att konvertera olika avgränsare till samma avgränsare. - Använd
REPLACE()
funktion för att injicera XML-stängnings- och öppningstaggar för att skapa ett XML-fragment - Använd
CAST(expr AS XML)
funktion för att konvertera ovanstående fragment till XML-datatypen - Använd
OUTER APPLY
för att tillämpa den tabellvärdade funktionennodes()
för att dela upp XML-fragmentet i dess ingående XML-taggar. Detta returnerar varje XML-tagg på en separat rad. - Extrahera bara värdet från XML-taggen med
value()
funktion och returnerar värdet med den angivna datatypen. - Lägg till ett kommatecken efter det ovan nämnda värdet.
- Observera att dessa värden returneras på separata rader. Användningen av
DISTINCT
nyckelordet tar nu bort dubbletter av rader (dvs värden). - 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