2014-09-08 5 views
0

У меня есть таблица со столбцом «дата» и «имя». Здесь вы можете найти образец таблицы: http://sqlfiddle.com/#!2/eddede/1Pivot SQL table

Что мне нужно сделать, так это подсчет количества строк, которые человек имеет на каждый год. Если у человека нет значения в году X, вы должны увидеть 0. Порядок имен должен быть на общем счете текущего года DESC, поэтому на данный момент: 2014.

Я могу рассчитывать на каждый год/имя, но не уверен, что это нужно для сводной таблицы: http://sqlfiddle.com/#!2/eddede/3

Я хотел бы, что результат должен выглядеть следующим образом:

NAME  2012 2013 2014 TOTAL 
Person B  2  2  2  6 
Person C  0  1  2  3 
Person A  4  3  1  8 

Я пытался, но я получаю что-то вроде этого (So Я не пишу неправильный SQL-запрос ...)

2012 2013 2014 
    6  6  5 
+0

Если в MySQL лучше добавить его в тегах. –

ответ

7

Вы можете получить результат с помощью агрегатной функции с некоторой условной логикой, как выражение CASE:

select 
    name, 
    sum(case when year(date) = 2012 then 1 else 0 end) [2012], 
    sum(case when year(date) = 2013 then 1 else 0 end) [2013], 
    sum(case when year(date) = 2014 then 1 else 0 end) [2014], 
    count(*) Total 
from list 
group by name; 

См SQL Fiddle with Demo

Теперь, если значения года неизвестны, вам нужно будет использовать динамический SQL. Это создает строку в SQL, что вам нужно выполнить:

DECLARE @cols AS NVARCHAR(MAX), 
    @query AS NVARCHAR(MAX), 
    @orderby nvarchar(max) 

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

select @orderby = 'ORDER BY ['+cast(year(getdate()) as varchar(4)) + '] desc' 

set @query = 'SELECT name, ' + @cols + ', Total 
      from 
      (
       select name, year(date) dt, 
        count(*) over(partition by name) Total 
       from list 
      ) x 
      pivot 
      (
       count(dt) 
       for dt in (' + @cols + ') 
      ) p '+ @orderby 


exec sp_executesql @query; 

SQL Fiddle with Demo См

+0

+1 за наличие бриллианта – Kermit

+0

И как я могу заказать этот динамический запрос в текущем году? Потому что теперь Person A является первым, и он должен быть B (или C в моем (плохом) примере) – endeka

+0

@endeka Вы хотите, чтобы текущий год отображался в качестве первого столбца, я не совсем уверен, что вы спрашиваете? – Taryn

2

Я думаю, что это то, что вы ищете:

SELECT 
    name, 
    SUM(if(year(date) = 2012, 1, 0)) AS '2012', 
    SUM(if(year(date) = 2013, 1, 0)) AS '2013', 
    SUM(if(year(date) = 2014, 1, 0)) AS '2014' 
FROM list 
GROUP BY name; 

и с общим :)

SELECT 
    t.name, 
    t.`2012`, 
    t.`2013`, 
    t.`2014`, 
    t.`2012` + t.`2013` + t.`2014` as total 
FROM 
(
SELECT 
    name, 
    SUM(if(year(date) = 2012, 1, 0)) AS `2012`, 
    SUM(if(year(date) = 2013, 1, 0)) AS `2013`, 
    SUM(if(year(date) = 2014, 1, 0)) AS `2014` 
FROM list 
GROUP BY name 
) as t 
+0

Вы забыли общее ... ;-) –

+0

Tnx для ответа. Но год не может быть жестко запрограммирован, поэтому я искал решение с сводной таблицей ... – endeka

+1

Насколько я знаю, столбцы для сводных таблиц должны быть жестко закодированы ... если вам нужна динамика в в сводной таблице вам нужно обернуть создание запроса в t-sql, php, C# и т. д. –