2016-08-03 59 views
0

我有一个使用计数表插入指定月份的缺失行的查询。该查询测试一个月是否缺少一天,然后从列中获取不同的值(在该月),并将这些值和缺失的日期值插入表中。从不同的表中获取价值并在不同的查询中使用价值

该表用于监控工作人员的工作日期,时间以及他们工作的部分。问题是中的某一列如果工作人员移动部分,Distinct语句会为该特定日期创建两组行。

这是工作的是获得意外的结果查询,(@Zohar佩莱德帮助我做到这一点)

DECLARE @startdt DATETIME = '2016/6/1'; 
DECLARE @enddt DATETIME = '2016/7/1'; 
DECLARE @value nvarchar(50); 


DECLARE @T as TABLE 
(
    Staff_ID int, 
    [Date]  date, 
    [Year]  int, 
    Mon   int, 
    [Day]  int, 
    First_Name varchar(10), 
    Last_Name varchar(10), 
    Section  varchar(10), 
    Time_Worked datetime 
) 

INSERT INTO @T VALUES 
(1001, '2016-06-01', 2016, 6, 1, 'Bill', 'Price', 'Level 1', '2016-06-01 8:30:00.000'), 
(1001, '2016-06-02', 2016, 6, 2, 'Bill', 'Price', 'Level 1', '2016-06-02 8:30:00.000'), 
(1001, '2016-06-03', 2016, 6, 3, 'Bill', 'Price', 'Level 1', '2016-06-03 8:30:00.000'), 
(1001, '2016-06-04', 2016, 6, 4, 'Bill', 'Price', 'Level 1', '2016-06-04 8:30:00.000'), 
(1001, '2016-06-05', 2016, 6, 5, 'Bill', 'Price', 'Level 1', '2016-06-05 8:30:00.000'), 
(1001, '2016-06-06', 2016, 6, 6, 'Bill', 'Price', 'Level 1', '2016-06-06 8:30:00.000'), 
(1001, '2016-06-07', 2016, 6, 7, 'Bill', 'Price', 'Level 2', '2016-06-07 8:30:00.000'),-- Different section 
(1001, '2016-07-05', 2016, 7, 5, 'Bill', 'Price', 'Level 2', '2016-07-5 8:30:00.000'), 
(1002, '2016-06-01', 2016, 6, 1, 'Mary', 'Somers', 'Level 1', '2016-06-01 8:30:00.000'), 
(1002, '2016-06-05', 2016, 6, 5, 'Mary', 'Somers', 'Level 1', '2016-06-05 8:30:00.000'), 
(1002, '2016-06-08', 2016, 6, 8, 'Mary', 'Somers', 'Level 1', '2016-06-08 8:30:00.000'), 
(1003, '2016-06-03', 2016, 6, 3, 'Mark', 'Jones', 'Level 1', '2016-06-03 8:30:00.000'), 
(1003, '2016-06-04', 2016, 6, 4, 'Mark', 'Jones', 'Level 1', '2016-06-05 8:30:00.000') 

[email protected] = SELECT Section_Data FROM Staff_Manager.dbo.Staff_Data_TBL WHERE Staff_No = 1001 


SET NOCOUNT ON; 
          IF object_id('dbo.Tally') is not null drop table dbo.tally 

          SELECT TOP 30000 IDENTITY(int,1,1) as ID 
           INTO dbo.Tally FROM master.dbo.SysColumns 
           ALTER table dbo.Tally 
           add constraint PK_ID primary key clustered(ID) 
          ; WITH Calendar AS 
          (
           SELECT dateadd(DD, ID-1, @startdt) as [Date] 
            FROM dbo.Tally 
            WHERE dateadd(DD, ID-1, @startdt) < @enddt 
          ) 


          INSERT INTO @T(Staff_ID, [Date], [Year], Mon, [Day], First_Name, Last_Name, Section) 
          SELECT DISTINCT Staff_ID, C.[Date], Year(C.[Date]), MONTH(C.[Date]), DAY(C.[Date]), First_Name, Last_Name, Section 
          FROM @T T 
          CROSS APPLY 
          (
           SELECT Cal.[Date] 
           FROM Calendar Cal 
           WHERE MONTH(Cal.[Date]) = MONTH(T.[Date]) 
           AND YEAR(Cal.[Date]) = YEAR(T.[Date]) 
           AND NOT EXISTS 
           (
            SELECT 1 
            FROM @T T2 
            WHERE T.Staff_ID = T2.Staff_ID 
            AND T2.[Date] = Cal.[Date] 
           ) 
          ) C 

          SELECT Staff_ID, [Date], [Year], Mon, [Day], First_Name, Last_Name, Section, Time_Worked 
           FROM @T 
           ORDER BY Staff_ID, [Date] 

这是结果,正如你可以看到它会为工作人员Bill Price两天由于2016-06-08由于他将SectionLevel 1更改为Level 2。因为Distinct声明将从Section列获得两个值。

(运行代码,你会得到所有的结果,这只是展示一下我的意思是SNIPPIT。)

Staff_ID Date Year Mon Day First_Name Last_Name Section Time_Worked 
1001 2016-06-01 2016 6 1 Bill Price Level 1 2016-06-01 08:30:00.000 
1001 2016-06-02 2016 6 2 Bill Price Level 1 2016-06-02 08:30:00.000 
1001 2016-06-03 2016 6 3 Bill Price Level 1 2016-06-03 08:30:00.000 
1001 2016-06-04 2016 6 4 Bill Price Level 1 2016-06-04 08:30:00.000 
1001 2016-06-05 2016 6 5 Bill Price Level 1 2016-06-05 08:30:00.000 
1001 2016-06-06 2016 6 6 Bill Price Level 1 2016-06-06 08:30:00.000 
1001 2016-06-07 2016 6 7 Bill Price Level 2 2016-06-07 08:30:00.000 
1001 2016-06-08 2016 6 8 Bill Price Level 1 NULL 
1001 2016-06-08 2016 6 8 Bill Price Level 2 NULL 
1001 2016-06-09 2016 6 9 Bill Price Level 1 NULL 
1001 2016-06-09 2016 6 9 Bill Price Level 2 NULL 
1001 2016-06-10 2016 6 10 Bill Price Level 1 NULL 
1001 2016-06-10 2016 6 10 Bill Price Level 2 NULL 
1001 2016-06-11 2016 6 11 Bill Price Level 1 NULL 
1001 2016-06-11 2016 6 11 Bill Price Level 2 NULL 
1001 2016-06-12 2016 6 12 Bill Price Level 1 NULL 
1001 2016-06-12 2016 6 12 Bill Price Level 2 NULL 
1001 2016-06-13 2016 6 13 Bill Price Level 1 NULL 
1001 2016-06-13 2016 6 13 Bill Price Level 2 NULL 

所以我保存的工作人员目前部分中的另一表,看代码下面。

DECLARE @value nvarchar(50); 

DECLARE @T3 as TABLE 
(
    Staff_ID int,  
    First_Name varchar(10), 
    Last_Name varchar(10), 
    Section  varchar(10) 

) 

INSERT INTO @T3 VALUES 
(1001, 'Bill', 'Price', 'Level 2'), 
(1002, 'Mary', 'Somers', 'Level 1'), 
(1003, 'Mark', 'Jones', 'Level 1') 


SELECT Section FROM @T3 WHERE Staff_ID = 1001 

结果如下,得到该职员的数据为Section。现在

Level 2 

,如果我能得到这个值,并把它作为在Section列,将解决我的问题的默认值。

此代码显然是不正确,但而不是获取Section列的distinct值,替换与来自其他表@T3, 像这样的东西的价值是价值,

@value = SELECT Section FROM @T3 WHERE Staff_ID = 1001 

再有值插入到新行中。

DECLARE @value nvarchar(50); 

@value = SELECT Section FROM @T3 WHERE Staff_ID = 1001 

INSERT INTO @T(Staff_ID, [Date], [Year], Mon, [Day], First_Name, Last_Name, Section) 
          SELECT DISTINCT Staff_ID, C.[Date], Year(C.[Date]), MONTH(C.[Date]), DAY(C.[Date]), First_Name, Last_Name, @value 
          FROM @T T 
          CROSS APPLY 
          (
           SELECT Cal.[Date] 
           FROM Calendar Cal 
           WHERE MONTH(Cal.[Date]) = MONTH(T.[Date]) 
           AND YEAR(Cal.[Date]) = YEAR(T.[Date]) 
           AND Section = @value 
           AND NOT EXISTS 
           (
            SELECT 1 
            FROM @T T2 
            WHERE T.Staff_ID = T2.Staff_ID 
            AND T2.[Date] = Cal.[Date] 
           ) 
          ) C 

任何帮助将不胜感激。

+0

一名员工会在一天多于一节的工作中工作吗? – Squirrel

+0

@Squirrel,不,他们可能会在月中改变,就是这样。 – KyloRen

+0

是否有任何你存储员工变更部分的日期? – Squirrel

回答

1

看到内码

; WITH Calendar AS 
(
     SELECT dateadd(DD, ID-1, @startdt) as [Date] 
     FROM dbo.Tally 
     WHERE dateadd(DD, ID-1, @startdt) < @enddt -- changed for better performance 
) 
INSERT INTO @T(Staff_ID, [Date], [Year], Mon, [Day], First_Name, Last_Name, Section) 
SELECT DISTINCT Staff_ID, C.[Date], Year(C.[Date]), MONTH(C.[Date]), DAY(C.[Date]), First_Name, Last_Name, S.Section -- changed to use S.Section 
FROM @T T 
    CROSS APPLY 
    (
     SELECT Cal.[Date] 
     FROM Calendar Cal    
     WHERE MONTH(Cal.[Date]) = MONTH(T.[Date]) 
     AND  YEAR(Cal.[Date]) = YEAR(T.[Date]) 
     AND  NOT EXISTS 
       (
        SELECT * 
        FROM @T T2 
        WHERE T.Staff_ID = T2.Staff_ID 
        AND  T2.[Date] = Cal.[Date] 
       ) 
    ) C 
    OUTER APPLY -- added to get last known section based on date 
    (
     SELECT TOP 1 Section 
     FROM @T x 
     WHERE x.Staff_ID = T.Staff_ID 
     AND x.Date  < C.Date 
     ORDER BY x.Date DESC 
    ) S 

意见,如果没有任何记录外发现APPLY和你要显示的均流段,加入到@ T3,并从那里

获得部分
+0

你是个天才!让我测试一下真实的数据库,我会尽快回复你。 – KyloRen

+0

非常感谢您的帮助。一个问题,我没有使用'加入',我会在哪里以及如何实现它。为了记录,这个问题得到了回答,我只是想知道,供将来参考。 – KyloRen

+0

有几种'join'类似'INNER JOIN','LEFT OUTER JOIN','RIGHT OUTER JOIN'。基本上你会使用'JOIN'将多个表连接在一起。最常见的是“INNER JOIN”。您可以搜索或拾取SQL上的任何书籍,以了解有关各种类型连接的更多信息 – Squirrel