一行中有多个记录

时间:2017-12-26 14:20:03

标签: sql sql-server sql-server-2008 sql-server-2012 sql-server-2008-r2

我有一张表EmpLunch如下:

get()

我需要根据以下逻辑在一个附加列ErrorCode中填充数据:

EmployeeId    BusinessDate    PunchIn   Lunch1Start   Lunch1End Lunch2Start Lunch2End   PunchOut
101            10/12/2017     9:00 AM   1:00 PM       1:30 PM                           5:00 PM
101            10/13/2017     9:00 AM   1:00 PM       1:28 PM                           5:00 PM
101            10/14/2017     9:00 AM   1:00 PM       1:28 PM    3:00 PM    3:28 PM     5:00 PM
101            10/15/2017     9:00 AM                                                   5:00 PM 

结果表应该是:

Error Code =
1 = Lunch 1 Not Taken
2 = Lunch 1 Less Than 30 Minutes
3 = Lunch 1 Started 300 Minutes Past IN Punch
4 = Lunch 2 Not Taken
5 = Lunch 2 Less Than 30 Minutes

我写了一个简单的代码,如下所示:

EmployeeId    BusinessDate    PunchIn   Lunch1Start   Lunch1End Lunch2Start Lunch2End   PunchOut    ErrorCode
101            10/12/2017     9:00 AM   1:00 PM       1:30 PM                           5:00 PM     4
101            10/13/2017     9:00 AM   1:00 PM       1:28 PM                           5:00 PM     2, 4
101            10/14/2017     9:00 AM   1:00 PM       1:28 PM    3:00 PM    3:28 PM     5:00 PM     2, 5
101            10/15/2017     9:00 AM                                                   5:00 PM     1

上述查询未在单元格中给出多条记录(如上面结果表中10/13和10/14的记录)。我的查询只给出了列中的第一个值。请建议一种实现目标的方法(逗号分隔列中的多个值)。

3 个答案:

答案 0 :(得分:3)

你只需要连续三个不同案例的结果。第一个用于错误代码1和2,第二个用于错误代码3,第三个用于代码4和5.像这样:

Select 
    *,  STUFF(CASE WHEN Lunch1Start IS NULL THEN ', 1' WHEN DATEDIFF(MINUTE, Lunch1Start, Lunch1End) < 30.0 THEN ', 2' ELSE '' END
    + CASE WHEN DATEDIFF(MINUTE, LunchEnd1, PunchIn) < 300.0 THEN ', 3' ELSE '' END
    + CASE WHEN Lunch2Start IS NULL THEN ', 4' WHEN DATEDIFF(MINUTE, Lunch2End, LunchI2Start) < 30.0 THEN ', 5' ELSE '' END,1,2,'') LunchError
From EmpLunch

答案 1 :(得分:3)

您可以使用连接在一起的单独case表达式来获取单独的值。这是一种方法:

select el.*,
       stuff( (case when Lunch1Start is null then ', 1' else '' end) +
              (case when datediff(minute, Lunch1Start, Lunch1End) < 30 then ', 2' else '' end) +
              (case when datediff(minute, LunchEnd1, PunchIn) < 300 then ', 3' else '' end) +
              (case when Lunch2Start IS NULL then ', 4' else '' end) +
              (case when datediff(minute, Lunch2End, LunchI2Start) < 30 then ', 5' else '' end), 1, 2, '')
from EmpLunch el;

stuff()删除分隔符。另请注意,如果没有错误,此版本将返回空字符串 - 而不是NULL。如果您需要NULL,请使用nullif()

select el.*,
       nullif(stuff( (case when Lunch1Start is null then ', 1' else '' end) +
                     (case when datediff(minute, Lunch1Start, Lunch1End) < 30 then ', 2' else '' end) +
                     (case when datediff(minute, LunchEnd1, PunchIn) < 300 then ', 3' else '' end) +
                     (case when Lunch2Start IS NULL then ', 4' else '' end) +
                     (case when datediff(minute, Lunch2End, LunchI2Start) < 30 then ', 5' else '' end), 1, 2, ''), '')
from EmpLunch el;

请注意datediff()返回一个整数。它也可能不会完全符合您的要求,因为它会计算值之间的“单位边界”。我会用这个逻辑代替:

select el.*,
       stuff( (case when Lunch1Start is null then ', 1' else '' end) +
              (case when Lunch1Start < dateadd(minute, -30, Lunch1End) then ', 2' else '' end) +
              (case when LunchEnd1 < dateadd(minute, -300) < 300 then ', 3' else '' end) +
              (case when Lunch2Start IS NULL then ', 4' else '' end) +
              (case when Lunch2End < dateadd(minute, -30, LunchI2Start) then ', 5' else '' end), 1, 2, '')
from EmpLunch el;

答案 2 :(得分:0)

矿山工作:

    DROP TABLE IF EXISTS category --SQL 2016/17
    go
    CREATE TABLE Category
    (id int IDENTITY (1,1) NOT NULL Primary Key
    ,Punchin time
    ,lunch1Start time 
    ,lunch1End time
    ,lunch2Start time
    ,lunch2End time
    ,Punchout time
    ,LunchError as CASE when lunch1start is null then '1' WHEN DATEDIFF(MINUTE,lunch1start,lunch1end) < 30 THEN '2' 
        WHEN DATEDIFF(MINUTE,lunch1end, punchin) < 300 THEN '3'  
        WHEN lunch2start is null then '4' end
        +   ', '+  CASE WHEN lunch2start  is null then '4' WHEN DATEDIFF(MINUTE,lunch2start,lunch2end) < 30 THEN '5' 
        WHEN DATEDIFF(MINUTE,lunch2start,lunch2end) < 300 THEN '3' 
        END  

    )

    INSERT category(punchin, lunch1Start, lunch1End, Punchout) 
    VALUES ('9:00 am','1:00 pm', '1:30 pm', '5:00 pm')

    INSERT category(punchin, lunch1Start, lunch1End, Punchout) 
    VALUES('9:00 am','1:00 pm', '1:28 pm', '5:00 pm')

    INSERT category(punchin, lunch1Start, lunch1End, lunch2Start, lunch2End, Punchout) 
    VALUES ('9:00 am','1:00 pm', '1:28 pm', '3:00 pm', '3:28','5:00 pm')

    INSERT category(punchin,  Punchout) 
    VALUES ('9:00 am','5:00 pm')
相关问题