2010-12-04 10 views
5

¿Cómo convierto un campo de lista de coma en una fila y lo visualizo en una columna?TSQL Seleccionar la lista de coma en las filas

Por ejemplo,

ID | Colour 
------------ 
1 | 1,2,3,4,5 

a:

ID | Colour 
------------ 
1 | 1 
1 | 2 
1 | 3 
1 | 4 
1 | 5 
+0

y una pregunta que se ha hecho muchas veces antes ... un ejemplo: http://stackoverflow.com/questions/4250475/split-one-column-into-multiple-rows –

+0

@Mark Byers: estas bases de datos el diseño está optimizado para almacenar listas de algo así como un sitio web PHP. Es horrible para las personas de SQL pero conveniente para los desarrolladores de front-end. – Andomar

Respuesta

5

La forma habitual de resolver esto es para crear una función de división. Puede obtener uno de Google, por ejemplo this one from SQL Team. Una vez que haya creado la función, se puede usar como:

create table colours (id int, colour varchar(255)) 
insert colours values (1,'1,2,3,4,5') 

select colours.id 
,  split.data 
from colours 
cross apply 
     dbo.Split(colours.colour, ',') as split 

Esta impresora:

id data 
1  1 
1  2 
1  3 
1  4 
1  5 
+0

seleccione dbo.XW_Wheels.ID, dbo.Splitter (XW_Wheels.Colours, ' ') de XW_Wheels cruz se aplican dbo.Splitter (XW_Wheels.Colours,',') como Split y me sale este mensaje "No se encuentra bien columna "dbo" o la función definida por el usuario o agregar "dbo.Splitter", o el nombre es ambiguo ". – Rya

+0

seleccione dbo.XW_Wheels.ID, dividir de XW_Wheels cruz se aplican dbo.Splitter (XW_Wheels.Colours, '') como fracción y me sale "nombre de columna no válido 'divide'." – Rya

+0

La función 'dbo.Split' devuelve una tabla. Intenta seleccionar 'split.data' en lugar de solo' split'. – Andomar

2

Otra posible solución es utilizar XML (suponiendo que están trabajando con SQL Server 2005 o superior):

DECLARE @s TABLE 
    (
     ID INT 
    , COLOUR VARCHAR(MAX) 
    ) 

INSERT INTO @s 
VALUES (1, '1,2,3,4,5') 

SELECT s.ID, T.Colour.value('.', 'int') AS Colour 
FROM (SELECT ID 
        , CONVERT(XML, '<row>' + REPLACE(Colour, ',', '</row><row>') + '</row>') AS Colour 
      FROM  @s a 
     ) s 
     CROSS APPLY s.Colour.nodes('row') AS T(Colour) 
+0

mejor aún: SELECT T.name.value ('.' 'Nvarchar (4000)') como el color FROM (SELECT CONVERT (XML, '' + Sustituir (nombre,' '' ') +' ') AS Nombre FROM (SELECT' 1, 2,3,4,5 'nombre) a ) s CROSS APPLY s.Name.nodes (' row ') AS T (nombre) – kerem

1

Sé que esta es una publicación anterior, pero pensé en agregar una actualización. Los divisores basados ​​en tablas Tally Table y cteTally tienen todos un problema importante. Usan delimitadores concatenados y eso mata su velocidad cuando los elementos se hacen más amplios y las cadenas se hacen más largas.

He solucionado ese problema y escribí un artículo al respecto que se puede encontrar en la siguiente URL. http://www.sqlservercentral.com/articles/Tally+Table/72993/

El nuevo método sopla las puertas fuera de toda bucle while, CTE recursiva, y XML métodos para VARCHAR (8000).

También le diré que un tipo con el nombre de "Peter" hizo una mejora incluso a ese código (en la discusión del artículo). El artículo sigue siendo interesante y voy a actualizar los archivos adjuntos con las mejoras de Peter en el próximo día o dos. Entre mi mejora principal y la tweek que hizo Peter, no creo que encuentres una solución T-SQL-Only más rápida para dividir VARCHAR (8000). También resolví el problema para esta clase de divisores para VARCHAR (MAX) y también estoy escribiendo un artículo para eso.

Cuestiones relacionadas