我想在SQL服务器上SUM时间值

时间:2014-07-02 17:21:00

标签: sql sql-server sql-server-2008

SELECT DISTINCT (DATEDIFF(DAY, '2014-06-01', '2014-06-30') + 1) - DATEDIFF(WEEK, '2014-06-01', '2014-06-30') * 2 - (CASE WHEN DATEPART(WEEKDAY, '2014-06-01') = 5 THEN 1 ELSE 0 END) - (CASE WHEN DATEPART(WEEKDAY, '2014-06-30') = 6 THEN 1 ELSE 0 END) AS TotalWorkingDays, COUNT(DISTINCT DATEADD(d, 0,DATEDIFF(d, 0, CHECKINOUT.CHECKTIME))) AS workingdays,
 USERINFO.NAME,
case when  '08:00:00.000' > cast(convert(char(8),min(checktime),8) as datetime) THEN NULL
ELSE 
cast(dateadd(minute,datediff(minute,'08:00:00.000',min(checktime)),'00:00')AS dateTIME) END as LATEIN ,
case when '17:00:00.000' < cast(convert(char(8),max(checktime),8) as datetime) THEN NULL 
ELSE
cast(dateadd(minute,datediff(minute,max(checktime),'17:00:00.000'),'00:00')AS dateTIME)END as LATEOUT     
FROM   USERINFO left JOIN CHECKINOUT ON CHECKINOUT.USERID = USERINFO.USERID 
left join departments on deptid = userinfo.DEFAULTDEPTID
WHERE(DEPARTMENTS.DEPTNAME = 'GEN/SUP-TBL') AND (CHECKINOUT.CHECKTIME >='2014-06-01') AND (CHECKINOUT.CHECKTIME <='2014-06-30') and name='Gokul Gopalakrishnan'
GROUP BY USERINFO.NAME,checktime

这是我的查询,它给出了以下输出:

TotalWorkingDays    workingdays NAMER   LATEIN                          LATEOUT
22                  1           abc      NULL                   1785-07-17 09:24:00.000
22                  1           abc      NULL                   1785-07-18 00:15:00.000
22                  1           abc      NULL                   1785-07-31 00:30:00.000
22                  1           abc    2014-06-01 00:39:00.000  1785-08-02 01:00:00.000
22                  1           abc    2014-06-01 09:14:00.000     NULL

但现在我想要输出如下:

TotalWorkingDays    workingdays NAME    TOTAL LATEIN        TOTAL LATEOUT
22                    5         abc     09:53:00.000       10:69:00.000

有没有办法做到这一点????

1 个答案:

答案 0 :(得分:2)

完整工作:

  1. 我们首先将时间转换为所需输出中的字符串格式。使用convert(nvarchar(50),time,121)
  2. 然后我们每次设置子串,以便它可以加在一起。
  3. 在求和之前,我们必须将字符串强制转换为数值
  4. 现在我们有了总和来确保正确的0领先填充权('00 +转换......)
  5. 导致:

    Select 
      TotalWorkingDays, 
      sum(workingDays) as WorkingDays,
      Namer,  
      right('00'+convert(varchar,sum(cast(substring(convert(nvarchar(50),LateIn,121),12,2) as Numeric(2,0)))),2)+ ':'+
      right('00'+convert(varchar,sum(cast(substring(convert(nvarchar(50),LateIn,121),15,2) as Numeric(2,0)))),2)+ ':'+      
      right('00'+convert(varchar,sum(cast(substring(convert(nvarchar(50),LateIn,121),18,2) as Numeric(2,0)))),2)+ ':'+     
      right('00'+convert(varchar,sum(cast(substring(convert(nvarchar(50),LateIn,121),21,3) as Numeric(3,0)))),3) as LateIn,
      right('00'+convert(varchar,sum(cast(substring(convert(nvarchar(50),LateOut,121),12,2) as Numeric(2,0)))),2)+ ':'+
      right('00'+convert(varchar,sum(cast(substring(convert(nvarchar(50),LateOut,121),15,2) as Numeric(2,0)))),2)+ ':'+      
      right('00'+convert(varchar,sum(cast(substring(convert(nvarchar(50),LateOut,121),18,2) as Numeric(2,0)))),2)+ ':'+     
      right('00'+convert(varchar,sum(cast(substring(convert(nvarchar(50),LateOut,121),21,3) as Numeric(3,0)))),3) as LateOut 
    from blue
    Group by TotalWorkingDays, namer
    

    使用这个例子 http://sqlfiddle.com/#!3/81c0c/2/0

    然而,这是一个重大问题

    假设总计小时,分钟或秒超过2位数。你的53代替...... 100 ......会发生什么?目前,这只会看两个最正确的角色会发生什么?

    您的输出不能是datetime数据类型,因为69不是有效分钟...如10:69:00.000,因此输出;所以输出是varchar,或者你的预期结果不正确。

    现在集成到您现有的查询中:

    With CTE as (
    SELECT DISTINCT (DATEDIFF(DAY, '2014-06-01', '2014-06-30') + 1) - DATEDIFF(WEEK, '2014-06-01', '2014-06-30') * 2 - (CASE WHEN DATEPART(WEEKDAY, '2014-06-01') = 5 THEN 1 ELSE 0 END) - (CASE WHEN DATEPART(WEEKDAY, '2014-06-30') = 6 THEN 1 ELSE 0 END) AS TotalWorkingDays, COUNT(DISTINCT DATEADD(d, 0,DATEDIFF(d, 0, CHECKINOUT.CHECKTIME))) AS workingdays,
     USERINFO.NAME,
    case when  '08:00:00.000' > cast(convert(char(8),min(checktime),8) as datetime) THEN NULL
    ELSE 
    cast(dateadd(minute,datediff(minute,'08:00:00.000',min(checktime)),'00:00')AS dateTIME) END as LATEIN ,
    case when '17:00:00.000' < cast(convert(char(8),max(checktime),8) as datetime) THEN NULL 
    ELSE
    cast(dateadd(minute,datediff(minute,max(checktime),'17:00:00.000'),'00:00')AS dateTIME)END as LATEOUT     
    FROM   USERINFO left JOIN CHECKINOUT ON CHECKINOUT.USERID = USERINFO.USERID 
    left join departments on deptid = userinfo.DEFAULTDEPTID
    WHERE(DEPARTMENTS.DEPTNAME = 'GEN/SUP-TBL') AND (CHECKINOUT.CHECKTIME >='2014-06-01') AND (CHECKINOUT.CHECKTIME <='2014-06-30') and name='Gokul Gopalakrishnan'
    GROUP BY USERINFO.NAME,checktime)
      Select 
          TotalWorkingDays, 
          sum(workingDays) as WorkingDays,
          Namer,  
          right('00'+convert(varchar,sum(cast(substring(convert(nvarchar(50),LateIn,121),12,2) as Numeric(2,0)))),2)+ ':'+
          right('00'+convert(varchar,sum(cast(substring(convert(nvarchar(50),LateIn,121),15,2) as Numeric(2,0)))),2)+ ':'+      
          right('00'+convert(varchar,sum(cast(substring(convert(nvarchar(50),LateIn,121),18,2) as Numeric(2,0)))),2)+ ':'+     
          right('00'+convert(varchar,sum(cast(substring(convert(nvarchar(50),LateIn,121),21,3) as Numeric(3,0)))),3) as LateIn,
          right('00'+convert(varchar,sum(cast(substring(convert(nvarchar(50),LateOut,121),12,2) as Numeric(2,0)))),2)+ ':'+
          right('00'+convert(varchar,sum(cast(substring(convert(nvarchar(50),LateOut,121),15,2) as Numeric(2,0)))),2)+ ':'+      
          right('00'+convert(varchar,sum(cast(substring(convert(nvarchar(50),LateOut,121),18,2) as Numeric(2,0)))),2)+ ':'+     
          right('00'+convert(varchar,sum(cast(substring(convert(nvarchar(50),LateOut,121),21,3) as Numeric(3,0)))),3) as LateOut 
        from CTE
        Group by TotalWorkingDays, namer
    

    或旧的激情......

     Select 
          TotalWorkingDays, 
          sum(workingDays) as WorkingDays,
          Namer,  
          right('00'+convert(varchar,sum(cast(substring(convert(nvarchar(50),LateIn,121),12,2) as Numeric(2,0)))),2)+ ':'+
          right('00'+convert(varchar,sum(cast(substring(convert(nvarchar(50),LateIn,121),15,2) as Numeric(2,0)))),2)+ ':'+      
          right('00'+convert(varchar,sum(cast(substring(convert(nvarchar(50),LateIn,121),18,2) as Numeric(2,0)))),2)+ ':'+     
          right('00'+convert(varchar,sum(cast(substring(convert(nvarchar(50),LateIn,121),21,3) as Numeric(3,0)))),3) as LateIn,
          right('00'+convert(varchar,sum(cast(substring(convert(nvarchar(50),LateOut,121),12,2) as Numeric(2,0)))),2)+ ':'+
          right('00'+convert(varchar,sum(cast(substring(convert(nvarchar(50),LateOut,121),15,2) as Numeric(2,0)))),2)+ ':'+      
          right('00'+convert(varchar,sum(cast(substring(convert(nvarchar(50),LateOut,121),18,2) as Numeric(2,0)))),2)+ ':'+     
          right('00'+convert(varchar,sum(cast(substring(convert(nvarchar(50),LateOut,121),21,3) as Numeric(3,0)))),3) as LateOut 
        from (
        SELECT DISTINCT (DATEDIFF(DAY, '2014-06-01', '2014-06-30') + 1) - DATEDIFF(WEEK, '2014-06-01', '2014-06-30') * 2 - (CASE WHEN DATEPART(WEEKDAY, '2014-06-01') = 5 THEN 1 ELSE 0 END) - (CASE WHEN DATEPART(WEEKDAY, '2014-06-30') = 6 THEN 1 ELSE 0 END) AS TotalWorkingDays, COUNT(DISTINCT DATEADD(d, 0,DATEDIFF(d, 0, CHECKINOUT.CHECKTIME))) AS workingdays,
         USERINFO.NAME,
        case when  '08:00:00.000' > cast(convert(char(8),min(checktime),8) as datetime) THEN NULL
        ELSE 
        cast(dateadd(minute,datediff(minute,'08:00:00.000',min(checktime)),'00:00')AS dateTIME) END as LATEIN ,
        case when '17:00:00.000' < cast(convert(char(8),max(checktime),8) as datetime) THEN NULL 
        ELSE
        cast(dateadd(minute,datediff(minute,max(checktime),'17:00:00.000'),'00:00')AS dateTIME)END as LATEOUT     
        FROM   USERINFO left JOIN CHECKINOUT ON CHECKINOUT.USERID = USERINFO.USERID 
        left join departments on deptid = userinfo.DEFAULTDEPTID
        WHERE(DEPARTMENTS.DEPTNAME = 'GEN/SUP-TBL') AND (CHECKINOUT.CHECKTIME >='2014-06-01') AND (CHECKINOUT.CHECKTIME <='2014-06-30') and name='Gokul Gopalakrishnan'
        GROUP BY USERINFO.NAME,checktime) blue
        Group by TotalWorkingDays, namer