Podejście
Poniższe podejście może służyć do deduplikacji rozdzielonej listy wartości.
- Użyj
REPLACE()
funkcja konwertowania różnych ograniczników w ten sam ogranicznik. - Użyj
REPLACE()
funkcja do wstrzykiwania znaczników zamykających i otwierających XML w celu utworzenia fragmentu XML - Użyj
CAST(expr AS XML)
funkcja do konwersji powyższego fragmentu na typ danych XML - Użyj
OUTER APPLY
zastosować funkcję wartości w tabelinodes()
aby podzielić fragment XML na jego składowe znaczniki XML. Zwraca każdy tag XML w osobnym wierszu. - Wyodrębnij tylko wartość ze znacznika XML za pomocą
value()
funkcji i zwraca wartość przy użyciu określonego typu danych. - Dołącz przecinek po wyżej wymienionej wartości.
- Pamiętaj, że te wartości są zwracane w osobnych wierszach. Użycie
DISTINCT
słowo kluczowe usuwa teraz zduplikowane wiersze (tj. wartości). - Użyj
FOR XML PATH('')
klauzula, aby połączyć wartości z wielu wierszy w jeden wiersz.
Zapytanie
Umieszczenie powyższego podejścia w formularzu zapytania:
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('')
Wkład i wynik
Biorąc pod uwagę dane wejściowe:
Powyższe zapytanie zwróci wynik:
Zwróć uwagę na końcowy przecinek na końcu. Zostawię to jako ćwiczenie, aby to usunąć.
EDYCJA:liczba duplikatów
OP poprosił w komentarzu „Jak uzyskać również liczbę duplikatów? w osobnej kolumnie
Najprostszym sposobem byłoby użycie powyższego zapytania, ale usunięcie ostatniej linii FOR XML PATH('')
. Następnie zliczanie wszystkich wartości i odrębnych wartości zwracanych przez SELECT
wyrażenie w powyższym zapytaniu (np. PivotedTable.PivotedColumn.value('.','nvarchar(max)')
). Różnica między liczbą wszystkich wartości a liczbą odrębnych wartości to liczba zduplikowanych wartości.
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)
Dla tych samych danych wejściowych pokazanych powyżej dane wyjściowe tego zapytania to:
CountOfAllValues CountOfUniqueValues CountOfDuplicateValues
---------------- ------------------- ----------------------
8 4 4