一行中有多个记录

问题描述 投票:2回答:3

我有一个表EmpLunch如下:

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 

我需要根据以下逻辑在一个额外的列ErrorCode中填充数据:

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

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

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

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

sql sql-server sql-server-2008 sql-server-2012 sql-server-2008-r2
3个回答
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

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;

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')
© www.soinside.com 2019 - 2024. All rights reserved.