如何将行旋转为列,并按过去 7 天显示 - SQL SERVER
Posted
技术标签:
【中文标题】如何将行旋转为列,并按过去 7 天显示 - SQL SERVER【英文标题】:How to pivot Rows as columns, and show by the last 7 days - SQL SERVER 【发布时间】:2020-12-18 11:09:46 【问题描述】:我正在尝试获取过去 7 天(不包括今天)的员工时间
我有一个看起来像这样的结果表
|EmpID | Date | Totaltime|
|------|------------|----------|
|1001 | 2020-12-17 | 1000 |
|1001 | 2020-12-16 | 2641 |
|1001 | 2020-12-14 | 1532 |
我需要将日期行作为从第 1 天(昨天)到第 7 天(8 天前)倒退的列
结果应该是这样的:
|EmpID | Day1 | Day2 | Day3 | Day4 | Day5 | Day6 | Day7 |
|------|------|------|------|------|------|------|------|
|1001 | 1000 | 2641 | | 1532 | | | |
如您所见,Day3、Day5、Day6、Day7 是空的,因为它们没有值。
我似乎找不到实现这一目标的快速方法。 PIVOT 功能需要您硬编码不适合的日期,因为我并不总是知道日期。
【问题讨论】:
【参考方案1】:您可以像这样使用日期算术和条件聚合:
select empid,
max(case when date = dateadd(day, -1, convert(date, getdate())) then totaltime end) as day1,
max(case when date = dateadd(day, -2, convert(date, getdate())) then totaltime end) as day2,
...
from mytable
group by empid
【讨论】:
【参考方案2】:给你,这是一个始终使用过去 7 天的动态数据透视表。如果您希望输出为第 1 天、第 2 天、第 3 天等,并且不知道如何自己执行此操作,我可以编辑查询。此外,正如您在输出中看到的那样,如果您不想要总和,只需将其更改为 MAX,这将重新计算总和 od Totaltime。
DROP TABLE IF EXISTS #tbl;
CREATE TABLE #tbl(EmpId int, [Date] date, Totaltime int);
INSERT INTO #tbl(EmpId, [Date], Totaltime)
VALUES (1001 , '2020-12-17' , 1000)
,(1001 , '2020-12-16' , 241)
,(1001 , '2020-12-14' , 1532)
,(1002 , '2020-12-17' , 100)
,(1002 , '2020-12-16' , 23641)
,(1003 , '2020-12-14' , 153)
,(1003 , '2020-12-11' , 200)
,(1003 , '2020-12-11' , 300);
DECLARE @sql nvarchar(max);
DECLARE @columnname nvarchar(max);
;with cte as
(SELECT dateadd(day,-1,CAST(GETDATE() AS date)) AS dt
UNION ALL
SELECT dateadd(day,-1,cte.dt)
FROM cte
WHERE cte.dt>dateadd(day,-7,CAST(GETDATE() AS date))
)
SELECT @columnname=COALESCE(@columnname+ ',', '') + QUOTENAME(CAST(cte.dt AS nvarchar(20)),'[]')
FROM cte;
/*USE MAX INSTEAD OF SUM BELOW IF YOU JUST WANT VALUES AND NOT A SUM*/
SET @sql='
SELECT *
FROM #tbl t
PIVOT
(SUM(TotalTime)
FOR [Date] IN('+@columnname+')) AS p'
EXECUTE sp_executesql @sql
输出:
【讨论】:
【参考方案3】:与另一个答案类似,这是一个动态脚本,它将始终抓取前 7 天并以它们为中心。它建立一个带有相关日期的临时表,string_agg 将它们放入一条记录中,然后将其传递给动态数据透视表。
DROP TABLE IF EXISTS #tbl;
CREATE TABLE #tbl(EmpId int, [Date] date, Totaltime int);
INSERT INTO #tbl(EmpId, [Date], Totaltime)
VALUES (1001 , '2020-12-17' , 1000)
,(1001 , '2020-12-16' , 241)
,(1001 , '2020-12-14' , 1532)
,(1002 , '2020-12-17' , 100)
,(1002 , '2020-12-16' , 23641)
,(1003 , '2020-12-14' , 153)
,(1003 , '2020-12-11' , 200)
,(1003 , '2020-12-11' , 300);
DECLARE @Date DATE
SET @Date = DATEADD(DAY,-7,GETDATE())
DROP TABLE IF EXISTS #Date
CREATE TABLE #Date (Date DATE)
WHILE @Date <= DATEADD(DAY,-1,GETDATE())
BEGIN
INSERT INTO #Date VALUES (@Date)
SET @Date = DATEADD(DAY,1,@Date)
END
DECLARE @PivotDate VARCHAR(MAX)
SELECT
@PivotDate = STRING_AGG(CONCAT('[',Date,']'),',')
FROM #Date
DECLARE @SQL NVARCHAR(MAX)
SET @SQL =
'
SELECT
*
FROM #tbl
PIVOT
(
MAX(Totaltime)
FOR Date IN (' + @PivotDate + ')
) p'
EXEC sys.sp_executesql @SQL
【讨论】:
以上是关于如何将行旋转为列,并按过去 7 天显示 - SQL SERVER的主要内容,如果未能解决你的问题,请参考以下文章