【问题标题】:Dynamic SQL query to return results in columns以列形式返回结果的动态 SQL 查询
【发布时间】:2018-12-10 04:51:33
【问题描述】:

我有这个基本的数据库表,并且是 SQL 初学者。

+-------------+--------+----------+
|  location   |  Week  | Expenses |
+-------------+--------+----------+
| Backoffice  | 201851 |       80 |
| frontoffice | 201852 |      110 |
| Backoffice  | 201901 |      120 |
| Backoffice  | 201902 |       70 |
| frontoffice | 201903 |       68 |
+-------------+--------+----------+

有没有办法动态检索过去 5 周的结果,而不是每次都在我的数据透视表中硬编码?

这是我的代码:

  SELECT *  from
  (SELECT[week]
        ,[Expenses]
from [cafe].[dbo].[table]where location = 'Backoffice'
) as Total_Expenses pivot (sum([expenses]) for [week] in ([201902],[201903],[201904],[201905],[201906],[201907],[201908],[201909])) as pivotable;

我希望能够只输入“5”,它会显示过去 5 周。可能是“最大”公式”

【问题讨论】:

  • 什么RDBMS系统? SQL Server/MySQL/Oracle/等?
  • SQL Server - 抱歉,仍在学习站点规则
  • 是的,你是对的

标签: sql sql-server sql-server-2008 tsql pivot


【解决方案1】:

如果您想选择前 5 周(最近几周),请使用 TOPSee here

SELECT TOP 5 *
FROM [cafe].[dbo].[table]
WHERE location = 'Backoffice'
ORDER BY Week Desc

将最后一行更改为ORDER BY Week [ ASC | DESC ] 以更改顺序。


如果您想获得前 5 周,并按周计算费用(我假设您想按周和位置分组),那么试试这个:

select top (5) Location, Week, sum(Expenses)
FROM table_name
WHERE location = 'backoffice'
GROUP BY Week, Location
Order By Week Desc

SQL Fiddle

附言我建议不要使用 [table] 作为您的表名

【讨论】:

  • 我的数据在同一周有多行#,这将它们相加吗?我追求的结果是这样的标题:位置 | 201915 | 201914 | 201913 | 201912
  • 不,你想把它们相加吗?
  • 是的,上面的数据只是一个示例,我有很多很多行
【解决方案2】:

您正在寻找一个支点。我建议条件聚合:

SELECT SUM(CASE WHEN weeknum = 1 THEN expenses END) as week_1,
       SUM(CASE WHEN weeknum = 2 THEN expenses END) as week_2,
       SUM(CASE WHEN weeknum = 3 THEN expenses END) as week_3,
       SUM(CASE WHEN weeknum = 4 THEN expenses END) as week_4,
       SUM(CASE WHEN weeknum = 5 THEN expenses END) as week_5       
FROM (SELECT t.*,
              ROW_NUMBER() OVER (ORDER BY WEEK DESC) as weeknum
      FROM [cafe].[dbo].[table] t
     ) t 
WHERE location = 'Backoffice';

请注意,这会旋转值,但会赋予它们通用名称。如果您确实想更改列的名称,则需要动态 SQL。

【讨论】:

  • 这有点类似于我在进入 pivot 之前所做的。问题是我可能需要持续 5 周,甚至可能需要持续 20 周
【解决方案3】:

要处理可变数量的列(周),您可以使用动态 TSQL:

create  table #tmp(location varchar(50), Week varchar(6),Expenses int)
insert into #tmp values
('Backoffice' ,'201851', 80),('frontoffice','201852',110),('Backoffice' ,'201901',120),('Backoffice' ,'201902', 70),('frontoffice','201903', 68)

declare @startDate date = '20190131' --Start date, probably you'll want to put Getdate() here
declare @weeks     table ([weekNumber] nvarchar(4), [weekYear] nvarchar(4))
declare @weekCount int = 10        --numbers of weeks to show
declare @counter   int = 0         --counter to loop on all weeks
declare @weekList  varchar(max)='' --holds the list of dynamically generated column headers 
declare @sql       varchar(max)='' --holds the complete dynamical TSQL query

set @counter = @weekCount
while @counter > 0
begin
    insert into @weeks 
    SELECT right('0' + cast(DATEPART(wk, DATEADD(WK,-(@counter),@startDate)) as varchar(2)),2)
           , DATEPART(year, DATEADD(WK,-(@counter),@startDate))
    set @counter = @counter - 1
end

select @weekList = @weekList + '[' + [weekYear] + [weekNumber] + '],' from @weeks 

set @weekList = SUBSTRING(@weekList, 1, len(@weekList) - 1)

set @sql = @sql + '  SELECT *  from'
set @sql = @sql + '  (SELECT[week]'
set @sql = @sql + '        ,[Expenses]'
set @sql = @sql + ' from #tmp where location = ''Backoffice'''
set @sql = @sql + ' ) as Total_Expenses pivot (sum([expenses]) for [week] in ('+@weekList+')) as pivotable;'

--execute dynamic query
exec(@sql)

输出@weekCount = 5:

输出@weekCount = 10:

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2014-06-26
    • 2019-01-16
    • 1970-01-01
    • 2018-12-29
    • 1970-01-01
    • 1970-01-01
    • 2017-09-17
    • 2018-10-05
    相关资源
    最近更新 更多