Aanpak
De volgende benadering kan worden gebruikt om een lijst met waarden met scheidingstekens te dedupliceren.
- Gebruik de
REPLACE()
functie om verschillende scheidingstekens om te zetten in hetzelfde scheidingsteken. - Gebruik de
REPLACE()
functie om XML-sluit- en openingstags te injecteren om een XML-fragment te maken - Gebruik de
CAST(expr AS XML)
functie om het bovenstaande fragment om te zetten in het XML-gegevenstype - Gebruik
OUTER APPLY
om de tabelwaardefunctienodes()
toe te passen om het XML-fragment te splitsen in zijn samenstellende XML-tags. Dit retourneert elke XML-tag op een aparte rij. - Extract alleen de waarde uit de XML-tag met behulp van de
value()
functie en retourneert de waarde met het opgegeven gegevenstype. - Voeg een komma toe na de bovengenoemde waarde.
- Houd er rekening mee dat deze waarden op afzonderlijke rijen worden geretourneerd. Het gebruik van de
DISTINCT
trefwoord verwijdert nu dubbele rijen (d.w.z. waarden). - Gebruik de
FOR XML PATH('')
clausule om de waarden over meerdere rijen samen te voegen tot één rij.
Zoekopdracht
De bovenstaande benadering in vraagvorm zetten:
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('')
Invoer en resultaat
Gezien de input:
De bovenstaande zoekopdracht geeft het resultaat:
Let op de afsluitende komma aan het einde. Ik laat het als een oefening aan jou over om dat te verwijderen.
BEWERK:Aantal duplicaten
OP gevraagd in een opmerking "hoe krijg ik ook het aantal duplicaten? in een aparte kolom ".
De eenvoudigste manier zou zijn om de bovenstaande query te gebruiken, maar de laatste regel te verwijderen FOR XML PATH('')
. Vervolgens worden alle waarden en afzonderlijke waarden geteld die worden geretourneerd door de SELECT
expressie in de bovenstaande query (d.w.z. PivotedTable.PivotedColumn.value('.','nvarchar(max)')
). Het verschil tussen het aantal van alle waarden en het aantal verschillende waarden is het aantal dubbele waarden.
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)
Voor dezelfde invoer als hierboven is de uitvoer van deze vraag:
CountOfAllValues CountOfUniqueValues CountOfDuplicateValues
---------------- ------------------- ----------------------
8 4 4