2008-10-13 25 views
7

necesito para girar una columna (columna de números). ejemplo necesitan estos datos:PIVOT en SQL 2005

a 1 
a 2 
b 3 
b 4 
c 5 
d 6 
d 7 
d 8 
d 9 
e 10 
e 11 
e 12 
e 13 
e 14 

tener este aspecto

a 1 2 
b 3 4 
c 5 
d 6 7 8 9 
e 10 11 12 13 14 

cualquier ayuda sería muy apreciada ...

+0

Parece que necesitas para limpiar el formato un poco. –

+0

¿Qué quiere decir con "tener este aspecto" exactamente? ¿Deseas todos los números para una fila en una sola columna, separados por espacios? – Blorgbeard

+0

columnas dinámicas o columna simple con coma separado. – IZar

Respuesta

1

Esta pregunta relacionada debe tener la respuesta que necesita: SQL Server: Examples of PIVOTing String data

control de una matriz en SSRS tiene columnas dinámicas, si estos datos se dirigía a un informe de todos modos, entonces podría usar eso. De lo contrario, tendrá que crear un procedimiento almacenado de SQL que genera el SQL como en los exaamples dinámicamente y luego lo ejecuta.

+0

BB gracias por responder. pero esto no funciona para mí. Necesito que mis columnas sean dinámicas. – IZar

+0

Usted puede superar ese problema mediante el uso de SQL dinámico. ¡Problema dinámico use SQL dinámico! :) (Lo he hecho antes con las fechas y funcionó bien.) – BoltBait

1

Simplemente porque quería conseguir un poco más de experiencia con el CTE, se me ocurrió lo siguiente:

WITH CTE(CTEstring, CTEids, CTElast_id) 
AS 
(
    SELECT string, CAST(id AS VARCHAR(1000)), id 
    FROM dbo.Test_Pivot TP1 
    WHERE NOT EXISTS (SELECT * FROM dbo.Test_Pivot TP2 WHERE TP2.string = TP1.string AND TP2.id < TP1.id) 
    UNION ALL 
    SELECT CTEstring, CAST(CTEids + ' ' + CAST(TP.id AS VARCHAR) AS VARCHAR(1000)), TP.id 
    FROM dbo.Test_Pivot TP 
    INNER JOIN CTE ON 
     CTE.CTEstring = TP.string 
    WHERE 
     TP.id > CTE.CTElast_id AND 
     NOT EXISTS (SELECT * FROM dbo.Test_Pivot WHERE string = CTE.CTEstring AND id > CTE.CTElast_id AND id < TP.id) 
) 
SELECT 
    t1.CTEstring, t1.CTEids 
FROM CTE t1 
INNER JOIN (SELECT CTEstring, MAX(LEN(CTEids)) AS max_len_ids FROM CTE GROUP BY CTEstring) SQ ON SQ.CTEstring = t1.CTEstring AND SQ.max_len_ids = LEN(t1.CTEids) 
ORDER BY CTEstring 
GO 

Se podría necesitar algunos ajustes, pero funcionó con su ejemplo

+0

Tom, No creo que esto funcione para mí porque cada grupo podría tener diferentes cantidades de valores. – IZar

+0

No veo cómo eso afectaría las cosas, a menos que la longitud de la cadena superara los 1000, lo cual puede manejar simplemente aumentando el tamaño de VARCHAR. El CTE es recursivo, no está realmente limitado por un número. –

0

No estoy seguro de que lo que está haciendo es realmente posible (o al menos práctico) en SQL hacer.

Se podría construir esa tabla dinámica en la aplicación cliente, por ejemplo, con:

select distinct Letter from MyTable 

para obtener la lista de letras, y luego usar una consulta con parámetros dentro de un bucle:

select Number from MyTable where Letter=:letter 

para obtener la lista de números para cada letra.

11

Usando ROW_NUMBER(), PIVOT y algo de SQL dinámico (pero ningún cursor es necesario):

CREATE TABLE [dbo].[stackoverflow_198716](
    [code] [varchar](1) NOT NULL, 
    [number] [int] NOT NULL 
) ON [PRIMARY] 

DECLARE @sql AS varchar(max) 
DECLARE @pivot_list AS varchar(max) -- Leave NULL for COALESCE technique 
DECLARE @select_list AS varchar(max) -- Leave NULL for COALESCE technique 

SELECT @pivot_list = COALESCE(@pivot_list + ', ', '') + '[' + CONVERT(varchar, PIVOT_CODE) + ']' 
     ,@select_list = COALESCE(@select_list + ', ', '') + '[' + CONVERT(varchar, PIVOT_CODE) + '] AS [col_' + CONVERT(varchar, PIVOT_CODE) + ']' 
FROM (
    SELECT DISTINCT PIVOT_CODE 
    FROM (
     SELECT code, number, ROW_NUMBER() OVER (PARTITION BY code ORDER BY number) AS PIVOT_CODE 
     FROM stackoverflow_198716 
    ) AS rows 
) AS PIVOT_CODES 

SET @sql = ' 
;WITH p AS (
    SELECT code, number, ROW_NUMBER() OVER (PARTITION BY code ORDER BY number) AS PIVOT_CODE 
    FROM stackoverflow_198716 
) 
SELECT code, ' + @select_list + ' 
FROM p 
PIVOT (
    MIN(number) 
    FOR PIVOT_CODE IN (
     ' + @pivot_list + ' 
    ) 
) AS pvt 
' 

PRINT @sql 

EXEC (@sql)