Consulta Transposición ciertas filas en nombres de columna
-
06-09-2019 - |
Pregunta
Tengo un par de mesas que se parecen a este Tabla 1
user_id | name
-------------------------
x111 | Smith, James
x112 | Smith, Jane
etc ..
Tabla 2
id | code | date | incident_code | user_id
-----------------------------------------------------------------
1 | 102008 | 10/20/2008 | 1 | x111
2 | 113008 | 11/30/2008 | 3 | x111
3 | 102008 | 10/20/2008 | 2 | x112
4 | 113008 | 11/30/2008 | 5 | x112
Lo que me gustaría ver es algo como esto
user_id | user_name | INCIDENT IN OCT 2008 | INCIDENT IN NOV 2008
------------------------------------------------------------------------------
x111 | Smith, John | 1 | 3
x112 | Smith, Jane | 2 | 5
etc ..
El incident_code sería sustituida por la descripción real del incidente que se encuentra en otra mesa, pero yo pensé que vería cómo funcionaría en primer lugar.
Algunos de los títulos de las columnas sería estática mientras que otros se crean a partir de la fecha. ¿Alguien se sabe cómo puedo hacer esto utilizando SQL Server 2005? Algunos ejemplos serían muy útiles.
Gracias de antemano
Solución
Esta es una solución que genera y ejecuta el SQL dinámico con un pivote:
DECLARE @pivot_list AS VARCHAR(MAX)
--
;
WITH cols
AS ( SELECT DISTINCT
'INCIDENT IN ' + LEFT(UPPER(CONVERT(VARCHAR, [date], 107)),
3) + ' '
+ SUBSTRING(UPPER(CONVERT(VARCHAR, [date], 107)), 9, 4) AS col
FROM so926209_2
)
SELECT @pivot_list = COALESCE(@pivot_list + ', ', '') + '[' + col + ']'
FROM cols
--
DECLARE @template AS VARCHAR(MAX)
SET @template = 'WITH incidents AS (
SELECT [user_id],
incident_code,
''INCIDENT IN '' + LEFT(UPPER(CONVERT(VARCHAR, [date], 107)), 3)
+ '' '' + SUBSTRING(UPPER(CONVERT(VARCHAR, [date], 107)), 9, 4) AS col
FROM so926209_2
)
,results AS (
SELECT * FROM incidents PIVOT (MAX(incident_code) FOR col IN ({@pivot_list})) AS pvt
)
SELECT results.[user_id]
,so926209_1.[name]
,{@select_list}
FROM results INNER JOIN so926209_1 ON so926209_1.[user_id] = results.[user_id]
'
DECLARE @sql AS VARCHAR(MAX)
SET @sql = REPLACE(REPLACE(@template, '{@pivot_list}', @pivot_list), '{@select_list}', @pivot_list)
--PRINT @sql
EXEC (@sql)
Cuando so926209_1
, so926209_2
son sus tablas 1 y 2
Tenga en cuenta que si tiene varios incidentes en un mes para la misma persona, su ejemplo no muestra cómo desea que manejaba. Este ejemplo sólo toma el último incidente en el mes.
Otros consejos
¿Quieres Pivotee http://msdn.microsoft.com/en-us/library/ms177410. aspx
Esto suena como una tarea de informes. La presentación de informes, a menudo referido desde una perspectiva de base de datos como OLAP, procesamiento Aanalytical línea, tiende a variar con bastante frecuencia del acceso de base de datos "tradicional", OLTP (Online Transaction Processing), ya que muy a menudo se compone de grandes agregaciones de datos que abarcan períodos más largos de tiempo. Con bastante frecuencia, el tipo de agregación que tu buscas.
El uso de un pivote como tetraneutrón sugirió será suficiente para los conjuntos de datos más pequeños. Sin embargo, como el volumen de datos que necesita para informar sobre crece, es posible que necesite algo más avanzado. OLAP se proporciona mediante SQL Server Analysis Services (SSAS), disponible en 2005 y 2008. El uso de SSAS puede crear repositorios de datos multidimensionales que los datos pre-agregados ya sea de una base de datos OLTP directamente, o desde una base de datos de almacenamiento de datos intermediario. datos multidimensionales (generalmente conocidos como cubos), proporcionan una forma mucho más rápida para acceder al tipo de datos que se pueden obtener de un pivote, sin interferir con el rendimiento de su procesamiento de transacciones estándar en su base de datos OLTP.
Si usted tiene más de una pequeña cantidad de datos que necesita para informar sobre, le recomiendo que echa un vistazo a SQL Server Analysis Services 2005, OLAP, cubos y MDX (Extensiones multidimensionales para T-SQL). Hay un learnig más grande curva de configurar un cubo OLAP, pero una vez que se ha configurado, los beneficios de tener uno puede ser enorme si tiene importantes necesidades de información.
Una consulta como esto funcionaría:
select
u.User_id,
u.Name,
Okt2008Sum = sum(case when i.date between
'2008-10-01' and '2008-11-01' then 1 else 0 end),
Nov2008Sum = sum(case when i.date between
'2008-11-01' and '2008-12-01'then 1 else 0 end)
from #incidents i
inner join #users u on i.user_id = u.user_id
group by u.user_id, u.name
En función de su cliente y con qué frecuencia hay que ejecutarlo, puede generar esta consulta. En SQL esto se vería así:
create table #months (
MonthName varchar(25),
StartDate datetime
)
insert into #months values ('Okt2008','2008-10-01')
insert into #months values ('Nov2008','2008-11-01')
declare @query varchar(8000)
select @query = 'select u.User_id, u.Name '
select @query = @query + ', ' + MonthName +
' = sum(case when i.date between ''' + cast(StartDate as varchar) +
''' and ''' + cast(dateadd(m,1,StartDate) as varchar) +
''' then 1 else 0 end) '
from #Months
select @query = @query + '
from #incidents i
inner join #users u on i.user_id = u.user_id
group by u.user_id, u.name'
exec (@query)