Enfoque
El siguiente enfoque se puede utilizar para eliminar los duplicados de una lista delimitada de valores.
- Use
REPLACE()
función para convertir diferentes delimitadores en el mismo delimitador. - Use
REPLACE()
función para inyectar etiquetas XML de cierre y apertura para crear un fragmento XML - Utilice
CAST(expr AS XML)
función para convertir el fragmento anterior en el tipo de datos XML - Utilice
OUTER APPLY
para aplicar la función con valores de tablanodes()
para dividir el fragmento XML en sus etiquetas XML constituyentes. Esto devuelve cada etiqueta XML en una fila separada. - Extrae solo el valor de la etiqueta XML usando
value()
y devuelve el valor utilizando el tipo de datos especificado. - Agregue una coma después del valor mencionado anteriormente.
- Tenga en cuenta que estos valores se devuelven en filas separadas. El uso de
DISTINCT
palabra clave ahora elimina filas duplicadas (es decir, valores). - Utilice
FOR XML PATH('')
cláusula para concatenar los valores en varias filas en una sola fila.
Consulta
Poniendo el enfoque anterior en forma de consulta:
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('')
Entrada y resultado
Dada la entrada:
La consulta anterior devolverá el resultado:
Fíjate en la coma final al final. Te lo dejo como ejercicio para eliminar eso.
EDITAR:Recuento de duplicados
OP solicitó en un comentario "¿cómo obtengo el recuento de duplicados también? en una columna separada ".
La forma más sencilla sería usar la consulta anterior pero eliminar la última línea FOR XML PATH('')
. Luego, contando todos los valores y valores distintos devueltos por SELECT
expresión en la consulta anterior (es decir, PivotedTable.PivotedColumn.value('.','nvarchar(max)')
). La diferencia entre el recuento de todos los valores y el recuento de valores distintos es el recuento de valores duplicados.
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)
Para la misma entrada que se muestra arriba, el resultado de esta consulta es:
CountOfAllValues CountOfUniqueValues CountOfDuplicateValues
---------------- ------------------- ----------------------
8 4 4