知道当前缺席的工作日期范围

时间:2017-02-22 13:16:41

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

Here is my table

我希望获得在给定日期范围内存在/不存在的所有用户。

CREATE TABLE [tt](
    [Id] [int] IDENTITY(1,1) NOT NULL,
    [UserId] [varchar](20) NULL,
    [EmpCode] [varchar](50) NULL,
    [Name] [varchar](200) NULL,
    [WorkDate] [varchar](20) NULL,
    [InTime] [varchar](20) NULL,
    [OutTime] [varchar](20) NULL,
    [TotalTime] [varchar](50) NULL,
)
insert into [tt] values
  ('106','E2E106','Goutam Kumar','2017-02-21','12:54:54 PM','10:06:42 PM','08:55:00')
 ,('106','E2E106','Goutam Kumar','2017-02-20','12:49:21 PM','09:26:27 PM','07:53:00')
 ,('106','E2E106','Goutam Kumar','2017-02-15','12:31:51 PM','09:21:14 PM','08:30:00')
 ,('106','E2E106','Goutam Kumar','2017-02-13','05:46:06 PM','09:32:17 PM','03:46:00')
 ,('106','E2E106','Goutam Kumar','2017-02-14','01:02:28 PM','09:32:50 PM','07:39:00')
 ,('111','E2E111','Mansi Manchanda','2017-02-21','12:42:42 PM','09:09:42 PM','08:07:00')
 ,('111','E2E111','Mansi Manchanda','2017-02-17','12:09:11 PM','09:40:46 PM','06:36:00')
 ,('111','E2E111','Mansi Manchanda','2017-02-16','11:56:21 AM','09:20:08 PM','08:07:00')
 ,('111','E2E111','Mansi Manchanda','2017-02-15','01:07:19 PM','09:57:40 PM','08:30:00')

 CREATE TABLE tUserInfo(
    [Id] [int] IDENTITY(1,1) NOT NULL,
    [UserId] [nvarchar](20) NULL,
    [Name] [nvarchar](200) NULL,
    [EmpCode] [varchar](200) NULL,
 )
INSERT into tUserInfo VALUES 
('106','Goutam Kumar','E2E106')      
,('111','Mansi Manchanda','E2E111')
,('112','Arvind Kumar Prajapati','E2E112')
,('116','Rahul Garg','E2E116')

我能够获得给定日期的用户的现状/缺席状态。 但我的问题是,我希望获得在给定日期范围内存在/不存在的所有用户。

我希望数据看起来像这样:

Id  UserId  Name            EmpCode InTime OutTime  WorkDate    Status
1   106 Goutam Kumar    E2E106                  2017-02-13  Present
2   111 Mansi Manchanda E2E111                  2017-02-14  Absent
3   112 Arvind Kumar    E2E112                  2017-02-14  Absent
4   116 Rahul Garg      E2E116                  2017-02-17  Absent

2 个答案:

答案 0 :(得分:3)

rextester:http://rextester.com/LCUT68753

使用outer apply()case表达式显示所有用户,并且缺席整个时间或至少出现一次:

declare @fromdate date = '20170201'
declare @thrudate date = '20170214'

select u.*
  , Status=case when x.WorkDate is null then 'Absent' else 'Present' end
from tUserInfo as u
outer apply (
  select top 1 tt.WorkDate 
  from tt
  where tt.UserId = u.UserId
    and tt.WorkDate >= @fromdate
    and tt.WorkDate <= @thrudate
    ) as x

返回:

+----+--------+------------------------+---------+---------+
| Id | UserId |          Name          | EmpCode | Status  |
+----+--------+------------------------+---------+---------+
|  1 |    106 | Goutam Kumar           | E2E106  | Present |
|  2 |    111 | Mansi Manchanda        | E2E111  | Absent  |
|  3 |    112 | Arvind Kumar Prajapati | E2E112  | Absent  |
|  4 |    116 | Rahul Garg             | E2E116  | Absent  |
+----+--------+------------------------+---------+---------+

使用not exists() <:p>的用户缺席整个持续时间

select * 
from tUserInfo as u
where not exists (
  select 1 
  from tt
  where tt.UserId = u.UserId
    and tt.WorkDate >= @fromdate
    and tt.WorkDate <= @thrudate
    )

返回:

+----+--------+------------------------+---------+
| Id | UserId |          Name          | EmpCode |
+----+--------+------------------------+---------+
|  2 |    111 | Mansi Manchanda        | E2E111  |
|  3 |    112 | Arvind Kumar Prajapati | E2E112  |
|  4 |    116 | Rahul Garg             | E2E116  |
+----+--------+------------------------+---------+

所有用户至少使用exists()

出席一次
select * 
from tUserInfo as u
where exists (
  select 1 
  from tt
  where tt.UserId = u.UserId
    and tt.WorkDate >= @fromdate
    and tt.WorkDate <= @thrudate
    )

返回:

+----+--------+--------------+---------+
| Id | UserId |     Name     | EmpCode |
+----+--------+--------------+---------+
|  1 |    106 | Goutam Kumar | E2E106  |
+----+--------+--------------+---------+

要知道在日期范围内每个workdate缺席的人和谁在场:

select 
    u.UserId
  , u.Name
  , d.WorkDate
  , [Status] = case when x.WorkDate is null then 'Absent' else 'Present' end
from (select distinct UserId, Name from tUserInfo) as u
  cross join (
    select distinct 
        WorkDate 
    from tt
    where tt.WorkDate >= @fromdate
      and tt.WorkDate <= @thrudate
      ) as d
outer apply (
  select top 1 tt.WorkDate 
  from tt
  where tt.UserId   = u.UserId
    and tt.WorkDate = d.WorkDate
    ) as x

返回:

+--------+------------------------+------------+---------+
| UserId |          Name          |  WorkDate  | Status  |
+--------+------------------------+------------+---------+
|    106 | Goutam Kumar           | 2017-02-13 | Present |
|    111 | Mansi Manchanda        | 2017-02-13 | Absent  |
|    112 | Arvind Kumar Prajapati | 2017-02-13 | Absent  |
|    116 | Rahul Garg             | 2017-02-13 | Absent  |
|    106 | Goutam Kumar           | 2017-02-14 | Present |
|    111 | Mansi Manchanda        | 2017-02-14 | Absent  |
|    112 | Arvind Kumar Prajapati | 2017-02-14 | Absent  |
|    116 | Rahul Garg             | 2017-02-14 | Absent  |
+--------+------------------------+------------+---------+

注意:这仅检查表workdate中存在的tt

如果您还需要检查指定日期范围内tt内不存在的日期,可以使用common table expression生成日期范围的日期:

set @fromdate = '20170212'
set @thrudate = '20170214'

;with n as (select n from (values(0),(1),(2),(3),(4),(5),(6),(7),(8),(9)) t(n))
, dates as (
  select top (datediff(day, @fromdate, @thrudate)+1) 
      [Date]=convert(date,dateadd(day
      , row_number() over (order by (select 1)) -1, @fromdate))
    from         n as deka
      cross join n as hecto      /* 100 days */
      --cross join n as kilo     /* 2.73 years */
      --cross join n as [tenK]    /* 27.3 years */
   order by [Date]
)
select 
    u.UserId
  , u.Name
  , WorkDate = convert(varchar(10),d.Date,120)
  , [Status] = case when x.WorkDate is null then 'Absent' else 'Present' end
from (select distinct UserId, Name from tUserInfo) as u
  cross join dates as d
outer apply (
  select top 1 tt.WorkDate 
  from tt
  where tt.UserId   = u.UserId
    and tt.WorkDate = d.Date
    ) as x    

返回:

+--------+------------------------+------------+---------+
| UserId |          Name          |  WorkDate  | Status  |
+--------+------------------------+------------+---------+
|    106 | Goutam Kumar           | 2017-02-12 | Absent  |
|    111 | Mansi Manchanda        | 2017-02-12 | Absent  |
|    112 | Arvind Kumar Prajapati | 2017-02-12 | Absent  |
|    116 | Rahul Garg             | 2017-02-12 | Absent  |
|    106 | Goutam Kumar           | 2017-02-13 | Present |
|    111 | Mansi Manchanda        | 2017-02-13 | Absent  |
|    112 | Arvind Kumar Prajapati | 2017-02-13 | Absent  |
|    116 | Rahul Garg             | 2017-02-13 | Absent  |
|    106 | Goutam Kumar           | 2017-02-14 | Present |
|    111 | Mansi Manchanda        | 2017-02-14 | Absent  |
|    112 | Arvind Kumar Prajapati | 2017-02-14 | Absent  |
|    116 | Rahul Garg             | 2017-02-14 | Absent  |
+--------+------------------------+------------+---------+

答案 1 :(得分:0)

使用pivot概念并获取所有日期,然后分别放置用户

DECLARE @cols AS NVARCHAR(MAX)
DECLARE @query  AS NVARCHAR(MAX)

SET @cols=STUFF((SELECT distinct ',' + QUOTENAME(c.WorkDate) 
            FROM tt c
            FOR XML PATH(''), TYPE
            ).value('.', 'NVARCHAR(MAX)') 
        ,1,1,'')


set @query = 'SELECT Id,UserId,EmpCode, ' + @cols + ' from 
            (
                select Id
                    , UserId
                    , EmpCode
                    ,Name
                    ,WorkDate

                from tt
           ) x
            pivot 
            (
                 max(Name)
                for WorkDate in (' + @cols + ')
            ) p '


execute(@query)

enter image description here