#sql #sql-server #pivot
#sql #sql-сервер #сводная
Вопрос:
Я пытаюсь получить сводные данные за некоторый год, чтобы получить совокупный итог по мере увеличения лет, а затем получить top 5.
Я попытался использовать SUM для total для лет в столбце year, но, похоже, она не увеличивается. Проблема, я думаю, связана с некоторыми потенциально нулевыми значениями?
Данные в таблице в настоящее время выглядят как
Name | ApplesEaten | Year
Bob | 2 | 2012
Bob | 5 | 2016
Elvis| 1 | 2017
Elvis| 2 | 2012
Sam | 8 | 2008
Elvis| 6 | 2004
Sam | 24 | 2019
Sarah| 14 | 2015
Bob | 6 | 2005
Rachel| 12 | 2010
Rachel| 10 | 2008
Bob | 82 | 2006
Но я стремлюсь получить его как
Name| 2004 | 2005 | 2006 .....
Bob | 0 | 6 | 88
Следующая проблема — получить top 5 в целом после завершения pivot!
Ответ №1:
Это то, что вы хотите?
select top (5) name,
sum(case when year <= 2005 then ApplesEaten else 0 end) as apples_2005,
sum(case when year <= 2006 then ApplesEaten else 0 end) as apples_2006,
. . .
sum(case when year <= 2019 then ApplesEaten else 0 end) as apples_2019
from t
group by name
order by sum(ApplesEaten) desc
Комментарии:
1. Есть ли способ сделать его динамичным? Вместо того, чтобы жестко указывать годы в?
2. и даст ли это мне top 5 в общей сложности после wards? или только первые 5?
3. @samsmith . . . Это дает top 5 на основе
order by
, который предположительно является общим. Если вы хотите динамический свод, вам нужно использовать динамический SQL. Это означает, что вам нужно сконструировать запрос в виде строки. Возможно, но намного сложнее.4. хорошо, это делает в значительной степени то, что я хочу, кроме добавления предыдущего года к текущему году. Итак, в моем примере Боб съел 6 яблок в 2005 году, а затем 82 в 2006 году, поэтому в 2006 году показано 88.
5. @samsmith . . . Если они являются совокупными, используйте
<=
. Я изменил ответ.
Ответ №2:
вы можете использовать вариант, когда
select top 5 name, max(case when year=2004 then ApplesEaten end ) [2004],
max(case when year=2005 then ApplesEaten end ) [2005],
max(case when year=2006 then ApplesEaten end ) [2006],
.......................
from table_name group by name
order by sum(ApplesEaten ) desc
Ответ №3:
Примерные данные
IF OBJECT_ID('tempdb..#Temp') IS NOT NULL
DROP TABLE #Temp
;WITH CTE(Name , ApplesEaten , [Year])
AS
(
SELECT 'Bob' , 2 , 2012 UNION ALL
SELECT 'Bob' , 5 , 2016 UNION ALL
SELECT 'Elvis', 1 , 2017 UNION ALL
SELECT 'Elvis', 2 , 2012 UNION ALL
SELECT 'Sam' , 8 , 2008 UNION ALL
SELECT 'Elvis', 6 , 2004 UNION ALL
SELECT 'Sam' , 24 , 2019 UNION ALL
SELECT 'Sarah', 14 , 2015 UNION ALL
SELECT 'Bob' , 6 , 2005 UNION ALL
SELECT 'Rachel', 12 , 2010 UNION ALL
SELECT 'Rachel', 10 , 2008 UNION ALL
SELECT 'Bob' , 82 , 2006
)
SELECT Name ,
ApplesEaten ,
[Year]
INTO #Temp
FROM CTE
Sql-скрипт, использующий динамический Sql
DECLARE @Columns nvarchar(max),
@IsnullColumns nvarchar(max),
@Sql nvarchar(max)
SELECT @Columns = STUFF((SELECT DISTINCT ', ' QUOTENAME([Year]) FROM #Temp FOR XML PATH ('')),1,1,'')
SELECT @IsnullColumns = STUFF((SELECT DISTINCT ', ' 'ISNULL(MAX(' QUOTENAME([Year]) '),''0'') AS apples_' CAST(([Year]) AS VARCHAR(20))
FROM #Temp FOR XML PATH ('')),1,1,'')
SET @Sql ='SELECT TOp 5 Name,' @IsnullColumns '
FROM
(
SELECT *,SUM(ApplesEaten) OVER(PARTITION BY Name ORDER BY [Year]) AS SumApplesEaten FROM #Temp
) AS PVT
PIVOT
(
MAX(SumApplesEaten) FOR [Year] IN (' @Columns ')
) AS PVT
GROUP BY Name
ORDER BY Name'
PRINT @Sql
EXEC (@Sql)