Подход
Следният подход може да се използва за премахване на дублиране на ограничен списък от стойности.
- Използвайте
REPLACE()
функция за преобразуване на различни разделители в един и същ разделител. - Използвайте
REPLACE()
функция за инжектиране на XML затварящи и отварящи тагове за създаване на XML фрагмент - Използвайте
CAST(expr AS XML)
функция за преобразуване на горния фрагмент в XML тип данни - Използвайте
OUTER APPLY
за да приложите функцията с таблични стойностиnodes()
за да разделите XML фрагмента на съставните му XML тагове. Това връща всеки XML таг на отделен ред. - Извлечете само стойността от XML тага с помощта на
value()
функция и връща стойността, използвайки посочения тип данни. - Добавете запетая след горепосочената стойност.
- Имайте предвид, че тези стойности се връщат на отделни редове. Използването на
DISTINCT
ключовата дума вече премахва дублиращи се редове (т.е. стойности). - Използвайте
FOR XML PATH('')
клауза за свързване на стойностите в множество редове в един ред.
Запитване
Поставяне на горния подход във формуляр за заявка:
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('')
Вход и резултат
Предвид входа:
Горната заявка ще върне резултата:
Обърнете внимание на запетаята в края. Ще ви оставя като упражнение да премахнете това.
РЕДАКТИРАНЕ:Брой дубликати
OP поиска в коментар „как да получа и броя на дубликатите? в отделна колона ".
Най-лесният начин би бил да използвате горната заявка, но да премахнете последния ред FOR XML PATH('')
. След това преброяване на всички стойности и различни стойности, върнати от SELECT
израз в горната заявка (т.е. PivotedTable.PivotedColumn.value('.','nvarchar(max)')
). Разликата между броя на всички стойности и броя на отделните стойности е броят на дублиращите се стойности.
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)
За същия вход, показан по-горе, резултатът от тази заявка е:
CountOfAllValues CountOfUniqueValues CountOfDuplicateValues
---------------- ------------------- ----------------------
8 4 4