多行的SQL求和时间

多行的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

我需要一些关于SQL语句的帮助。我试着用1到2行来总结时间。到目前为止,输出如下所示:

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)中选择*I
select,它就工作了?