sql >> Base de Datos >  >> RDS >> Sqlserver

¿Cómo hacer una tabla dinámica por año en SQL?

Deberá obtener el año para cada uno de sus valores de fecha y luego PIVOT en esos valores. Puede usar un par de funciones diferentes en SQL Server para obtener esto.

  • DatePart - la sintaxis sería DatePart(year, yourDate)
  • Año - la sintaxis es Year(yourDate)

Cualquiera de estos devolverá el año para cada fecha, luego colocará los años en su PIVOT como las nuevas columnas.

select plate, [2011], [2012], [2013], [2014], [2015], [2016], [2017]
from
(
  SELECT tnk.Plate, 
     Cast(mua.Tarih as Date) as M_Date,
     year(mua.Tarih) yr
  FROM Muayene mua 
  LEFT JOIN Tanker tnk 
    on (tnk.OID=mua.TankerId)
) d
pivot
(
  max(m_date)
  for yr in ([2011], [2012], [2013], [2014], [2015], [2016], [2017])
) piv;

Ver Demostración . Notarás que en esta consulta eliminé la columna mua.Id . Esto se debe a que cuando dinamiza los datos, los agrupará por cada columna en su consulta, dado que estos valores son distintos, devolverá filas diferentes. Al eliminar la columna de su consulta, obtendrá un resultado:

|    PLATE |       2011 |   2012 |   2013 |       2014 |       2015 |       2016 |       2017 |
|----------|------------|--------|--------|------------|------------|------------|------------|
| 34VM7969 | 2011-08-02 | (null) | (null) | 2014-08-08 | 2015-02-21 | 2016-08-19 | 2017-03-09 |

Finalmente, si va a tener un número desconocido de fechas, le sugiero 2 cosas:use una tabla de calendario y luego SQL dinámico.

Luego, la tabla de calendario es solo una lista de fechas que puede usar para realizar consultas similares a:

create table calendar
(
  date datetime
);

insert into calendar
select '2011-01-01' union all
select '2012-01-01' union all
select '2013-01-01' union all
select '2014-01-01' union all
select '2015-01-01' union all
select '2016-01-01' union all
select '2016-01-01' union all
select '2017-01-01' union all
select '2018-01-01' 

Luego crearía una lista de los años en una cadena sql y ejecutaría esa cadena, similar a:

DECLARE @cols AS NVARCHAR(MAX),
    @query  AS NVARCHAR(MAX)

select @cols = STUFF((SELECT ',' + QUOTENAME(year(date)) 
                    from calendar
                    group by year(date)
                    order by year(date)
            FOR XML PATH(''), TYPE
            ).value('.', 'NVARCHAR(MAX)') 
        ,1,1,'')

set @query = 'SELECT plate, ' + @cols + ' 
            from 
            (
              select plate, 
                m_Date = convert(varchar(10), m_date, 120), 
                year(m_date) yr
              from yourquery
            ) x
            pivot 
            (
                max(m_date)
                for yr in (' + @cols + ')
            ) p '

execute sp_executesql @query;

Ver Demostración