Sql 按小时显示“打开”记录数的数据透视表
我有一个包含两个重要字段的表。准备和完成 我希望我的输出给我24列,对应于一天中的一个小时,每个列给我仍然打开的记录数,这些记录在一小时结束前定义为ReadyDate,但在该时钟小时内的一小时结束后定义为CompleteDate 因此,诀窍在于一条记录可以出现在零列或多列中。在上午6:05和上午9:17已经完成的内容将出现在6:00a、7:00a和8:00a列上 因此,如果表中有以下条目Sql 按小时显示“打开”记录数的数据透视表,sql,sql-server,sql-server-2016,Sql,Sql Server,Sql Server 2016,我有一个包含两个重要字段的表。准备和完成 我希望我的输出给我24列,对应于一天中的一个小时,每个列给我仍然打开的记录数,这些记录在一小时结束前定义为ReadyDate,但在该时钟小时内的一小时结束后定义为CompleteDate 因此,诀窍在于一条记录可以出现在零列或多列中。在上午6:05和上午9:17已经完成的内容将出现在6:00a、7:00a和8:00a列上 因此,如果表中有以下条目 10-14-2019 06:05 10-14-2019 06:10 (this will popu
10-14-2019 06:05 10-14-2019 06:10 (this will populate no columns)
10-14-2019 07:12 10-14-2019 09:30 (this will populate the 7:00 hour and 8:00 hour)
10-14-2019 10:02 10-14-2019 13:55 (this will populate the 10:00 hour, 11:00, 12:00)
10-14-2019 12:50 10-14-2019 15:30 (this will populate the 12:00, 13:00, 14:00)
我希望我的输出有24列,其中包含以下数字
0,0,0,0,0,0,0,1,1,0,1,1,2,1,1,0,0,0,0,0,0,0,0
我不知道如何进行。如果您有任何见解,我们将不胜感激。这不是最漂亮的,但它确实如您所解释的那样有效。我希望看到一个更优雅的解决方案,如果有人有一个
DECLARE @t TABLE
(
date1 DATETIME NOT NULL,
date2 DATETIME NOT NULL
);
INSERT INTO @t
(
date1,
date2
)
VALUES
('10-14-2019 06:05', '10-14-2019 06:10'),
('10-14-2019 07:12', '10-14-2019 09:30'),
('10-14-2019 10:02', '10-14-2019 13:55'),
('10-14-2019 12:50', '10-14-2019 15:30');
SELECT SUM(t.[0]) AS [0],
SUM(t.[1]) AS [1],
SUM(t.[2]) AS [2],
SUM(t.[3]) AS [3],
SUM(t.[4]) AS [4],
SUM(t.[5]) AS [5],
SUM(t.[6]) AS [6],
SUM(t.[7]) AS [7],
SUM(t.[8]) AS [8],
SUM(t.[9]) AS [9],
SUM(t.[10]) AS [10],
SUM(t.[11]) AS [11],
SUM(t.[12]) AS [12],
SUM(t.[13]) AS [13],
SUM(t.[14]) AS [14],
SUM(t.[15]) AS [15],
SUM(t.[16]) AS [16],
SUM(t.[17]) AS [17],
SUM(t.[18]) AS [18],
SUM(t.[19]) AS [19],
SUM(t.[20]) AS [20],
SUM(t.[21]) AS [21],
SUM(t.[22]) AS [22],
SUM(t.[23]) AS [23]
FROM
(
SELECT id,
date1,
date2,
CASE
WHEN 0
BETWEEN DATEPART(HOUR, date1) AND DATEPART(HOUR, date2) - 1 THEN
1
ELSE
0
END AS [0],
CASE
WHEN 1
BETWEEN DATEPART(HOUR, date1) AND DATEPART(HOUR, date2) - 1 THEN
1
ELSE
0
END AS [1],
CASE
WHEN 2
BETWEEN DATEPART(HOUR, date1) AND DATEPART(HOUR, date2) - 1 THEN
1
ELSE
0
END AS [2],
CASE
WHEN 3
BETWEEN DATEPART(HOUR, date1) AND DATEPART(HOUR, date2) - 1 THEN
1
ELSE
0
END AS [3],
CASE
WHEN 4
BETWEEN DATEPART(HOUR, date1) AND DATEPART(HOUR, date2) - 1 THEN
1
ELSE
0
END AS [4],
CASE
WHEN 5
BETWEEN DATEPART(HOUR, date1) AND DATEPART(HOUR, date2) - 1 THEN
1
ELSE
0
END AS [5],
CASE
WHEN 6
BETWEEN DATEPART(HOUR, date1) AND DATEPART(HOUR, date2) - 1 THEN
1
ELSE
0
END AS [6],
CASE
WHEN 7
BETWEEN DATEPART(HOUR, date1) AND DATEPART(HOUR, date2) - 1 THEN
1
ELSE
0
END AS [7],
CASE
WHEN 8
BETWEEN DATEPART(HOUR, date1) AND DATEPART(HOUR, date2) - 1 THEN
1
ELSE
0
END AS [8],
CASE
WHEN 9
BETWEEN DATEPART(HOUR, date1) AND DATEPART(HOUR, date2) - 1 THEN
1
ELSE
0
END AS [9],
CASE
WHEN 10
BETWEEN DATEPART(HOUR, date1) AND DATEPART(HOUR, date2) - 1 THEN
1
ELSE
0
END AS [10],
CASE
WHEN 11
BETWEEN DATEPART(HOUR, date1) AND DATEPART(HOUR, date2) - 1 THEN
1
ELSE
0
END AS [11],
CASE
WHEN 12
BETWEEN DATEPART(HOUR, date1) AND DATEPART(HOUR, date2) - 1 THEN
1
ELSE
0
END AS [12],
CASE
WHEN 13
BETWEEN DATEPART(HOUR, date1) AND DATEPART(HOUR, date2) - 1 THEN
1
ELSE
0
END AS [13],
CASE
WHEN 14
BETWEEN DATEPART(HOUR, date1) AND DATEPART(HOUR, date2) - 1 THEN
1
ELSE
0
END AS [14],
CASE
WHEN 15
BETWEEN DATEPART(HOUR, date1) AND DATEPART(HOUR, date2) - 1 THEN
1
ELSE
0
END AS [15],
CASE
WHEN 16
BETWEEN DATEPART(HOUR, date1) AND DATEPART(HOUR, date2) - 1 THEN
1
ELSE
0
END AS [16],
CASE
WHEN 17
BETWEEN DATEPART(HOUR, date1) AND DATEPART(HOUR, date2) - 1 THEN
1
ELSE
0
END AS [17],
CASE
WHEN 18
BETWEEN DATEPART(HOUR, date1) AND DATEPART(HOUR, date2) - 1 THEN
1
ELSE
0
END AS [18],
CASE
WHEN 19
BETWEEN DATEPART(HOUR, date1) AND DATEPART(HOUR, date2) - 1 THEN
1
ELSE
0
END AS [19],
CASE
WHEN 20
BETWEEN DATEPART(HOUR, date1) AND DATEPART(HOUR, date2) - 1 THEN
1
ELSE
0
END AS [20],
CASE
WHEN 21
BETWEEN DATEPART(HOUR, date1) AND DATEPART(HOUR, date2) - 1 THEN
1
ELSE
0
END AS [21],
CASE
WHEN 22
BETWEEN DATEPART(HOUR, date1) AND DATEPART(HOUR, date2) - 1 THEN
1
ELSE
0
END AS [22],
CASE
WHEN 23
BETWEEN DATEPART(HOUR, date1) AND DATEPART(HOUR, date2) - 1 THEN
1
ELSE
0
END AS [23]
FROM @t
) t;
输出:
这不是最漂亮的,但正如你所解释的那样。我希望看到一个更优雅的解决方案,如果有人有一个
DECLARE @t TABLE
(
date1 DATETIME NOT NULL,
date2 DATETIME NOT NULL
);
INSERT INTO @t
(
date1,
date2
)
VALUES
('10-14-2019 06:05', '10-14-2019 06:10'),
('10-14-2019 07:12', '10-14-2019 09:30'),
('10-14-2019 10:02', '10-14-2019 13:55'),
('10-14-2019 12:50', '10-14-2019 15:30');
SELECT SUM(t.[0]) AS [0],
SUM(t.[1]) AS [1],
SUM(t.[2]) AS [2],
SUM(t.[3]) AS [3],
SUM(t.[4]) AS [4],
SUM(t.[5]) AS [5],
SUM(t.[6]) AS [6],
SUM(t.[7]) AS [7],
SUM(t.[8]) AS [8],
SUM(t.[9]) AS [9],
SUM(t.[10]) AS [10],
SUM(t.[11]) AS [11],
SUM(t.[12]) AS [12],
SUM(t.[13]) AS [13],
SUM(t.[14]) AS [14],
SUM(t.[15]) AS [15],
SUM(t.[16]) AS [16],
SUM(t.[17]) AS [17],
SUM(t.[18]) AS [18],
SUM(t.[19]) AS [19],
SUM(t.[20]) AS [20],
SUM(t.[21]) AS [21],
SUM(t.[22]) AS [22],
SUM(t.[23]) AS [23]
FROM
(
SELECT id,
date1,
date2,
CASE
WHEN 0
BETWEEN DATEPART(HOUR, date1) AND DATEPART(HOUR, date2) - 1 THEN
1
ELSE
0
END AS [0],
CASE
WHEN 1
BETWEEN DATEPART(HOUR, date1) AND DATEPART(HOUR, date2) - 1 THEN
1
ELSE
0
END AS [1],
CASE
WHEN 2
BETWEEN DATEPART(HOUR, date1) AND DATEPART(HOUR, date2) - 1 THEN
1
ELSE
0
END AS [2],
CASE
WHEN 3
BETWEEN DATEPART(HOUR, date1) AND DATEPART(HOUR, date2) - 1 THEN
1
ELSE
0
END AS [3],
CASE
WHEN 4
BETWEEN DATEPART(HOUR, date1) AND DATEPART(HOUR, date2) - 1 THEN
1
ELSE
0
END AS [4],
CASE
WHEN 5
BETWEEN DATEPART(HOUR, date1) AND DATEPART(HOUR, date2) - 1 THEN
1
ELSE
0
END AS [5],
CASE
WHEN 6
BETWEEN DATEPART(HOUR, date1) AND DATEPART(HOUR, date2) - 1 THEN
1
ELSE
0
END AS [6],
CASE
WHEN 7
BETWEEN DATEPART(HOUR, date1) AND DATEPART(HOUR, date2) - 1 THEN
1
ELSE
0
END AS [7],
CASE
WHEN 8
BETWEEN DATEPART(HOUR, date1) AND DATEPART(HOUR, date2) - 1 THEN
1
ELSE
0
END AS [8],
CASE
WHEN 9
BETWEEN DATEPART(HOUR, date1) AND DATEPART(HOUR, date2) - 1 THEN
1
ELSE
0
END AS [9],
CASE
WHEN 10
BETWEEN DATEPART(HOUR, date1) AND DATEPART(HOUR, date2) - 1 THEN
1
ELSE
0
END AS [10],
CASE
WHEN 11
BETWEEN DATEPART(HOUR, date1) AND DATEPART(HOUR, date2) - 1 THEN
1
ELSE
0
END AS [11],
CASE
WHEN 12
BETWEEN DATEPART(HOUR, date1) AND DATEPART(HOUR, date2) - 1 THEN
1
ELSE
0
END AS [12],
CASE
WHEN 13
BETWEEN DATEPART(HOUR, date1) AND DATEPART(HOUR, date2) - 1 THEN
1
ELSE
0
END AS [13],
CASE
WHEN 14
BETWEEN DATEPART(HOUR, date1) AND DATEPART(HOUR, date2) - 1 THEN
1
ELSE
0
END AS [14],
CASE
WHEN 15
BETWEEN DATEPART(HOUR, date1) AND DATEPART(HOUR, date2) - 1 THEN
1
ELSE
0
END AS [15],
CASE
WHEN 16
BETWEEN DATEPART(HOUR, date1) AND DATEPART(HOUR, date2) - 1 THEN
1
ELSE
0
END AS [16],
CASE
WHEN 17
BETWEEN DATEPART(HOUR, date1) AND DATEPART(HOUR, date2) - 1 THEN
1
ELSE
0
END AS [17],
CASE
WHEN 18
BETWEEN DATEPART(HOUR, date1) AND DATEPART(HOUR, date2) - 1 THEN
1
ELSE
0
END AS [18],
CASE
WHEN 19
BETWEEN DATEPART(HOUR, date1) AND DATEPART(HOUR, date2) - 1 THEN
1
ELSE
0
END AS [19],
CASE
WHEN 20
BETWEEN DATEPART(HOUR, date1) AND DATEPART(HOUR, date2) - 1 THEN
1
ELSE
0
END AS [20],
CASE
WHEN 21
BETWEEN DATEPART(HOUR, date1) AND DATEPART(HOUR, date2) - 1 THEN
1
ELSE
0
END AS [21],
CASE
WHEN 22
BETWEEN DATEPART(HOUR, date1) AND DATEPART(HOUR, date2) - 1 THEN
1
ELSE
0
END AS [22],
CASE
WHEN 23
BETWEEN DATEPART(HOUR, date1) AND DATEPART(HOUR, date2) - 1 THEN
1
ELSE
0
END AS [23]
FROM @t
) t;
输出:
编辑-针对1小时的班次进行了更正
这里有一个PIVOT选项,它使用一个特殊的理货表
午夜的滚动是有原因的
不清楚是否希望按日期显示行。如果不是的话,这将是一个小问题,以消除
范例
返回
编辑-针对1小时的班次进行了更正
这里有一个PIVOT选项,它使用一个特殊的理货表
午夜的滚动是有原因的
不清楚是否希望按日期显示行。如果不是的话,这将是一个小问题,以消除
范例
返回
关于您提供的数据示例,有一些问题。 还不完全清楚每个小时是如何选择的。如果某个项目处于活动状态的分钟数大于某个数字,是否会选择一小时?还有一个可能的问题,即CompletedDate在第二天。在这两种情况下,这里还有一个如何实现这一点的示例。你必须修改时间逻辑才能得到你需要的答案
DECLARE @data Table
(
id int identity(1,1)
,ReadyDate datetime
,CompletedDate datetime
,foo varchar(500)
)
INSERT INTO @data
VALUES
('10-14-2019 06:05','10-14-2019 06:10','(this will populate no columns)')
,('10-14-2019 07:12','10-14-2019 09:30','(this will populate the 7:00 hour and 8:00 hour)')
,('10-14-2019 10:02','10-14-2019 13:55','(this will populate the 10:00 hour, 11:00, 12:00)')
,('10-14-2019 12:50','10-14-2019 15:30','(this will populate the 12:00, 13:00, 14:00)')
;
;WITH Numbers AS
(
SELECT 1 AS Number
UNION ALL
SELECT Number+1
FROM Numbers
WHERE Number < 24
)
,src
as (
Select *,
flag = CASE WHEN Number >= DATEPART(hour, ReadyDate) AND Number < DATEPART(hour, ReadyDate) + DateDiff(hour, ReadyDate, CompletedDate) THEN 1 ELSE 0 END
from @Data
CROSS APPLY Numbers
)
Select *
from src
PIVOT
(
max(flag) for number in ([1],[2], [3], [4], [5], [6], [7], [8], [9], [10], [11], [12], [13], [14], [15], [16], [17], [18], [19], [20], [21], [22], [23], [24])
) as ptable
关于您提供的数据示例,有一些问题。 还不完全清楚每个小时是如何选择的。如果某个项目处于活动状态的分钟数大于某个数字,是否会选择一小时?还有一个可能的问题,即CompletedDate在第二天。在这两种情况下,这里还有一个如何实现这一点的示例。你必须修改时间逻辑才能得到你需要的答案
DECLARE @data Table
(
id int identity(1,1)
,ReadyDate datetime
,CompletedDate datetime
,foo varchar(500)
)
INSERT INTO @data
VALUES
('10-14-2019 06:05','10-14-2019 06:10','(this will populate no columns)')
,('10-14-2019 07:12','10-14-2019 09:30','(this will populate the 7:00 hour and 8:00 hour)')
,('10-14-2019 10:02','10-14-2019 13:55','(this will populate the 10:00 hour, 11:00, 12:00)')
,('10-14-2019 12:50','10-14-2019 15:30','(this will populate the 12:00, 13:00, 14:00)')
;
;WITH Numbers AS
(
SELECT 1 AS Number
UNION ALL
SELECT Number+1
FROM Numbers
WHERE Number < 24
)
,src
as (
Select *,
flag = CASE WHEN Number >= DATEPART(hour, ReadyDate) AND Number < DATEPART(hour, ReadyDate) + DateDiff(hour, ReadyDate, CompletedDate) THEN 1 ELSE 0 END
from @Data
CROSS APPLY Numbers
)
Select *
from src
PIVOT
(
max(flag) for number in ([1],[2], [3], [4], [5], [6], [7], [8], [9], [10], [11], [12], [13], [14], [15], [16], [17], [18], [19], [20], [21], [22], [23], [24])
) as ptable
用你正在使用的数据库标记你的问题。用你正在使用的数据库标记你的问题。问题是如果时间超过午夜,它将无法按预期工作。您的数据集会有这样的结果吗?问题是,如果时间滚动到午夜,它将无法按预期工作。您的数据集会有这样的结果吗?您的解决方案非常棒,我非常感谢。我仍然在学习这个例子,并且认为我理解其中的大部分。我必须添加自己的表,表中填充了0到23的值,因为我没有访问主数据库的权限。然而,它工作得非常好。我试图理解第一个交叉应用。不知何故,它使用了两次值表。我把这部分分成单独的部分来理解它。这是可行的,但我并不完全遵循逻辑。“你能解释一下吗?”亚伯拉罕·林肯很高兴这有帮助。CTE1将通过一个特殊的计数/数字表扩展每一行。CTE2将创建一个包含所有日期和时间组合的虚拟列表。。。这是一个小小的欺骗,以避免在最终透视中出现空值。最后的选择是cte1和cte2@AbrahamLincoln我应该补充说。。。在主动打破它方面做得很好,这就是我们学习的方式:您的解决方案非常棒,我非常感谢。我仍然在学习这个例子,并且认为我理解其中的大部分。我必须添加自己的表,表中填充了0到23的值,因为我没有访问主数据库的权限。然而,它工作得非常好。我试图理解第一个交叉应用。不知何故,它使用了两次值表。我把这部分分成单独的部分来理解它。这是可行的,但我并不完全遵循逻辑。“你能解释一下吗?”亚伯拉罕·林肯很高兴这有帮助。CTE1将通过一个特殊的计数/数字表扩展每一行。CTE2将创建一个包含所有日期和时间组合的虚拟列表。。。这是一个小小的欺骗,以避免在最终透视中出现空值。最后的选择是cte1和cte2@AbrahamLincoln我应该补充说。。。在主动打破它方面做得很好,这是我们学习的方式: