动态SQL查询以列形式返回结果

时间:2018-07-02 00:53:01

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

我有这个基本的数据库表,并且是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周。可能是通过“最大”公式”

3 个答案:

答案 0 :(得分:3)

如果要选择前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

P.S。我建议不要使用[table]作为您的表名

答案 1 :(得分: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。

答案 2 :(得分:1)

要处理可变数量的列(周),可以使用动态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

enter image description here

输出为@weekCount = 10

enter image description here