多行的SQL求和时间
我需要一些关于SQL语句的帮助。我试着用1到2行来总结时间。到目前为止,输出如下所示:多行的SQL求和时间,sql,sql-server,function,sum,Sql,Sql Server,Function,Sum,我需要一些关于SQL语句的帮助。我试着用1到2行来总结时间。到目前为止,输出如下所示: workingdate cin typecin cout typecout rn sum --------------------------------------------------------------------- 2021-05-03 07:49 K 13:31 G 1 05:42:00 202
workingdate cin typecin cout typecout rn sum
---------------------------------------------------------------------
2021-05-03 07:49 K 13:31 G 1 05:42:00
2021-05-03 14:01 K 16:17 G 2 02:16:00
2021-05-04 07:52 K 13:36 G 1 05:44:00
2021-05-04 14:04 K 16:22 G 2 02:18:00
...
这是我目前的代码:
WITH CTE AS
( SELECT chip_num, chip_user_id, chip_user,
CONVERT(DATE,[date]) workingdate,
(CASE WHEN [type] = 'K' THEN format([date], 'HH:mm', 'de-DE' ) ELSE NULL END) [cin],
(CASE WHEN [type] = 'K' THEN type ELSE NULL END) [typecin],
subtypein,
(CASE WHEN [type] = 'G' THEN format([date], 'HH:mm', 'de-DE' ) ELSE NULL END) [cout],
(CASE WHEN [type] = 'G' THEN type ELSE NULL END) [typecout],
subtypeout,
ROW_NUMBER() OVER(PARTITION BY chip_num,CONVERT(DATE,[date]), [type] ORDER BY [date]) rn
FROM app_terminal1
),
CTE1 AS
(
SELECT chip_num, chip_user_id, chip_user, workingdate,
LEFT(CONVERT(TIME(4),MIN([cin]),114),5) [cin],
LEFT(CONVERT(VARCHAR(10),MIN([typecin]),114),5) [typecin],
LEFT(CONVERT(VARCHAR(10),MAX([subtypein]),114),5) [subtypein],
LEFT(CONVERT(TIME(4),MIN([cout]),114),5) [cout],
LEFT(CONVERT(VARCHAR(10),MIN([typecout]),114),5) [typecout],
LEFT(CONVERT(VARCHAR(10),MAX([subtypeout]),114),5) [subtypeout],
FORMAT( DATEDIFF(MINUTE, LEFT(CONVERT(VARCHAR(10),MIN([cin]),114),5), LEFT(CONVERT(VARCHAR(10),MIN([cout]),114),5))/60, '00', 'en-US' ) as diffHour,
FORMAT( DATEDIFF(MINUTE, LEFT(CONVERT(VARCHAR(10),MIN([cin]),114),5), LEFT(CONVERT(VARCHAR(10),MIN([cout]),114),5))
- (DATEDIFF(MINUTE, LEFT(CONVERT(VARCHAR(10),MIN([cin]),114),5), LEFT(CONVERT(VARCHAR(10),MIN([cout]),114),5))/60) * 60,
'00', 'en-US' )as diffMin,
rn
FROM CTE
where chip_user_id = @ChipUserId and YEAR(workingdate) = @Year and MONTH(workingdate) = @Month
GROUP BY chip_num, chip_user_id, chip_user,workingdate, rn
),
CTE2 AS
(
select *, CONVERT(time, case when diffHour IS NULL THEN NULL ELSE CONCAT(diffHour, ':', diffMin) end) as sum from CTE1
)
select * from CTE2
我需要的输出:
我需要这样的东西,sum
在sumDay
中对一整天进行汇总。但是对rn
执行一些操作很重要,因为条目可能会有所不同。有时只有一排,或者可能是三排
workingdate cin typecin cout typecout rn sum sumDay
-----------------------------------------------------------------------------
2021-05-03 07:49 K 13:31 G 1 05:42:00
2021-05-03 14:01 K 16:17 G 2 02:16:00 07:58:00
2021-05-04 07:52 K 13:36 G 1 05:44:00
2021-05-04 14:04 K 16:22 G 2 02:18:00 08:02:00
...
样本数据:
表模式:
name - varchar(255)
serial - varchar(255)
chip_user_id - varchar(255)
chip_user - varchar(255)
chip_num - varchar(255)
date - datetime
type - varchar(255)
subtypein(255)
subtypein(255)
样本插入:
insert into app_terminal1 (name, serial, chip_user_id, chip_user, chip_num, date, type, subtypein, subtypeout)
VALUES
('Test', 'Test', '999', 'Test Test', '9092090', '2021-03-05 07:49:12.000', 'K', NULL, NULL),
('Test', 'Test', '999', 'Test Test', '9092090', '2021-03-05 13:31:12.000', 'G', NULL, NULL),
('Test', 'Test', '999', 'Test Test', '9092090', '2021-03-05 14:01:12.000', 'K', NULL, NULL),
('Test', 'Test', '999', 'Test Test', '9092090', '2021-03-05 16:17:12.000', 'G', NULL, NULL),
('Test', 'Test', '999', 'Test Test', '9092090', '2021-04-05 07:52:12.000', 'K', NULL, NULL),
('Test', 'Test', '999', 'Test Test', '9092090', '2021-04-05 13:36:12.000', 'G', NULL, NULL),
('Test', 'Test', '999', 'Test Test', '9092090', '2021-04-05 14:04:12.000', 'K', NULL, NULL),
('Test', 'Test', '999', 'Test Test', '9092090', '2021-04-05 16:22:12.000', 'G', NULL, NULL)
提前谢谢 给你。您可以使用left join加入每个工作日的
总和
WITH CTE AS
(SELECT chip_num, chip_user_id, chip_user,
CONVERT(DATE,[date]) workingdate,
(CASE WHEN [type] = 'K' THEN format([date], 'HH:mm', 'de-DE' ) ELSE NULL END) [cin],
(CASE WHEN [type] = 'K' THEN type ELSE NULL END) [typecin],
subtypein,
(CASE WHEN [type] = 'G' THEN format([date], 'HH:mm', 'de-DE' ) ELSE NULL END) [cout],
(CASE WHEN [type] = 'G' THEN type ELSE NULL END) [typecout],
subtypeout,
ROW_NUMBER() OVER(PARTITION BY chip_num,CONVERT(DATE,[date]), [type] ORDER BY [date] desc) rn
FROM app_terminal1
),
CTE1 AS
(
SELECT chip_num, chip_user_id, chip_user, workingdate,
LEFT(CONVERT(TIME(4),MIN([cin]),114),5) [cin],
LEFT(CONVERT(VARCHAR(10),MIN([typecin]),114),5) [typecin],
LEFT(CONVERT(VARCHAR(10),MAX([subtypein]),114),5) [subtypein],
LEFT(CONVERT(TIME(4),MIN([cout]),114),5) [cout],
LEFT(CONVERT(VARCHAR(10),MIN([typecout]),114),5) [typecout],
LEFT(CONVERT(VARCHAR(10),MAX([subtypeout]),114),5) [subtypeout],
FORMAT( DATEDIFF(MINUTE, LEFT(CONVERT(VARCHAR(10),MIN([cin]),114),5), LEFT(CONVERT(VARCHAR(10),MIN([cout]),114),5))/60, '00', 'en-US' ) as diffHour,
FORMAT( DATEDIFF(MINUTE, LEFT(CONVERT(VARCHAR(10),MIN([cin]),114),5), LEFT(CONVERT(VARCHAR(10),MIN([cout]),114),5))
- (DATEDIFF(MINUTE, LEFT(CONVERT(VARCHAR(10),MIN([cin]),114),5), LEFT(CONVERT(VARCHAR(10),MIN([cout]),114),5))/60) * 60,
'00', 'en-US' )as diffMin,
rn
FROM CTE
where chip_user_id = @ChipUserId and YEAR(workingdate) = @Year and MONTH(workingdate) = @Month
GROUP BY chip_num, chip_user_id, chip_user,workingdate, rn
),
CTE2 AS (
select *, CONVERT(time, case when diffHour IS NULL THEN NULL ELSE CONCAT(diffHour, ':', diffMin) end) as sumTot from CTE1
)
select t1.*,
+ right('00'+ cast(t2.tot%3600/60 AS VARCHAR(2)), 2) + ':'
+ right('00'+ cast(((t2.tot%3600)%60) AS VARCHAR(2)), 2) + ':'
+ '00' as sumDay
from CTE2 t1
left join
(select workingdate, sum(datediff(minute, '00:00:00', sumTot)) as tot from CTE2
group by workingdate) t2 on t2.workingdate = t1.workingdate and t1.rn = 1
order by workingdate, cin
试试这个,给你。您可以使用left join加入每个工作日的
总和
WITH CTE AS
(SELECT chip_num, chip_user_id, chip_user,
CONVERT(DATE,[date]) workingdate,
(CASE WHEN [type] = 'K' THEN format([date], 'HH:mm', 'de-DE' ) ELSE NULL END) [cin],
(CASE WHEN [type] = 'K' THEN type ELSE NULL END) [typecin],
subtypein,
(CASE WHEN [type] = 'G' THEN format([date], 'HH:mm', 'de-DE' ) ELSE NULL END) [cout],
(CASE WHEN [type] = 'G' THEN type ELSE NULL END) [typecout],
subtypeout,
ROW_NUMBER() OVER(PARTITION BY chip_num,CONVERT(DATE,[date]), [type] ORDER BY [date] desc) rn
FROM app_terminal1
),
CTE1 AS
(
SELECT chip_num, chip_user_id, chip_user, workingdate,
LEFT(CONVERT(TIME(4),MIN([cin]),114),5) [cin],
LEFT(CONVERT(VARCHAR(10),MIN([typecin]),114),5) [typecin],
LEFT(CONVERT(VARCHAR(10),MAX([subtypein]),114),5) [subtypein],
LEFT(CONVERT(TIME(4),MIN([cout]),114),5) [cout],
LEFT(CONVERT(VARCHAR(10),MIN([typecout]),114),5) [typecout],
LEFT(CONVERT(VARCHAR(10),MAX([subtypeout]),114),5) [subtypeout],
FORMAT( DATEDIFF(MINUTE, LEFT(CONVERT(VARCHAR(10),MIN([cin]),114),5), LEFT(CONVERT(VARCHAR(10),MIN([cout]),114),5))/60, '00', 'en-US' ) as diffHour,
FORMAT( DATEDIFF(MINUTE, LEFT(CONVERT(VARCHAR(10),MIN([cin]),114),5), LEFT(CONVERT(VARCHAR(10),MIN([cout]),114),5))
- (DATEDIFF(MINUTE, LEFT(CONVERT(VARCHAR(10),MIN([cin]),114),5), LEFT(CONVERT(VARCHAR(10),MIN([cout]),114),5))/60) * 60,
'00', 'en-US' )as diffMin,
rn
FROM CTE
where chip_user_id = @ChipUserId and YEAR(workingdate) = @Year and MONTH(workingdate) = @Month
GROUP BY chip_num, chip_user_id, chip_user,workingdate, rn
),
CTE2 AS (
select *, CONVERT(time, case when diffHour IS NULL THEN NULL ELSE CONCAT(diffHour, ':', diffMin) end) as sumTot from CTE1
)
select t1.*,
+ right('00'+ cast(t2.tot%3600/60 AS VARCHAR(2)), 2) + ':'
+ right('00'+ cast(((t2.tot%3600)%60) AS VARCHAR(2)), 2) + ':'
+ '00' as sumDay
from CTE2 t1
left join
(select workingdate, sum(datediff(minute, '00:00:00', sumTot)) as tot from CTE2
group by workingdate) t2 on t2.workingdate = t1.workingdate and t1.rn = 1
order by workingdate, cin
试试这个我对您的查询做了一些更改。基本上我避免在查询中格式化日期/时间。如果需要将其格式化为所需格式,请在最后一个
select
语句中执行,但不要在cte
中执行,这会使日期或时间所需的任何计算复杂化
要计算您的sum
列,请使用DATEDIFF()
在[date]
上使用MIN()
和MAX()
DATEDIFF(MINUTE, MIN(CONVERT(TIME(0), [date])), MAX(CONVERT(TIME(0), [date])))
要计算sum
列,使用window函数计算sumDay
SUM(diffTotalMin) OVER (PARTITION BY workingdate)
要转换为所需的时间格式,可以使用DATEADD(MINUTE,diffTotalMin,0)
我对您的查询做了一些更改。基本上我避免在查询中格式化日期/时间。如果需要将其格式化为所需格式,请在最后一个
select
语句中执行,但不要在cte
中执行,这会使日期或时间所需的任何计算复杂化
要计算您的sum
列,请使用DATEDIFF()
在[date]
上使用MIN()
和MAX()
DATEDIFF(MINUTE, MIN(CONVERT(TIME(0), [date])), MAX(CONVERT(TIME(0), [date])))
要计算sum
列,使用window函数计算sumDay
SUM(diffTotalMin) OVER (PARTITION BY workingdate)
要转换为所需的时间格式,可以使用DATEADD(MINUTE,diffTotalMin,0)
请用您正在使用的DBMS标记您的问题。您希望实现的输出是什么:问题开头的表格还是结尾的表格?请提供与您想要获得的样本结果相匹配的样本源数据。我想要获得的表就是最后的表。如何提供示例源数据?插入?是的。请在
插入到…
格式中包含表架构和示例数据好的,我已经完成了!请用您正在使用的DBMS标记您的问题。您希望实现的输出是什么:问题开头的表格还是结尾的表格?请提供与您想要获得的样本结果相匹配的样本源数据。我想要获得的表就是最后的表。如何提供示例源数据?插入?是的。请在插入到…
格式中包含表架构和示例数据好的,我已经完成了!谢谢但是它给了我一些错误2x不明确的列名workingdate
和操作数数据类型time对于sum运算符无效
并且为“CTE2”多次给出了rn列。
我能做些什么?@Timebreaker900,我更新了我的答案,如果可以提供数据的示例脚本,我放进样品里好多了data@Timebreaker900,我的查询正在运行,但试图获得结果,您可以检查几乎正确的内容。。我将最后一个rn重命名为rn2。但它会将条目颠倒过来。谢谢!但是它给了我一些错误2x不明确的列名workingdate
和操作数数据类型time对于sum运算符无效
并且为“CTE2”多次给出了rn列。
我能做些什么?@Timebreaker900,我更新了我的答案,如果可以提供数据的示例脚本,我放进样品里好多了data@Timebreaker900,我的查询正在运行,但试图获得结果,您可以检查几乎正确的内容。。我将最后一个rn重命名为rn2。但是它会把条目颠倒过来。这确实很好,等等,我会试试看。这很奇怪。。我在一个新函数中加入了完全相同的代码,但它不计算sumday你所说的不计算
是什么意思?试试dbfiddle演示,如果我select*from fGetterminalTimes4(052021,999)
sumDay为空,它就可以工作了。你能给我们看看你的函数吗?那真的很好,等等,我会试试的。这很奇怪。。我在一个新函数中加入了完全相同的代码,但它不计算sumday你所说的不计算
是什么意思?试试dbfiddle演示,如果我从fGetTerminalTimes4(0520211999)中选择*Iselect,它就工作了?