【问题标题】:Multiple records in one row一行中有多个记录
【发布时间】:2018-06-07 08:54:39
【问题描述】:

我有一个如下表 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


    【解决方案1】:

    您只需要连接三种不同情况的结果。第一个用于错误代码 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
    

    【讨论】:

      【解决方案2】:

      您可以使用连接在一起的单独的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;
      

      【讨论】:

        【解决方案3】:

        我的作品:

            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')
        

        【讨论】:

          猜你喜欢
          • 2020-12-22
          • 1970-01-01
          • 1970-01-01
          • 2020-12-12
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2016-01-19
          相关资源
          最近更新 更多