2016-08-03 9 views
0

タリーテーブルを使用して指定した月に欠落行を挿入するクエリがあります。問合せは、その月に1日が欠落しているかどうかを検査し、その月の列から個別の値を取得し、それらの値と欠落した日付値を表に挿入します。別のテーブルから値を取得し、別のクエリで値を使用する

テーブルは、勤務時間、勤務時間、勤務時間を監視するために使用されます。問題は、Sectionのスタッフのメンバが移動する場合、Distinct文がその特定の日。

これは、望ましくない結果を取得するクエリを、(@Zohar Peledは私がこれを行うに役立っ)

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のための二日間を作成し、見ることができるように取り組んでいますがLevel 1からLevel 2に変更されたため、2016-06-08がオンになりました。 Distinctステートメントは、Section列から2つの値を取得します。

(コードを実行し、すべての結果が得られます、これは私が何を意味するか表示するだけの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 

結果は以下のようになり、そのスタッフのデータはになります。

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

スタッフは1日に1つ以上のセクションで働くでしょうか? – Squirrel

+0

@Squirrel、No.彼らは中旬に変更されることがあります。 – KyloRen

+0

スタッフがセクションを変更したときの日付を保存する場所はどこですか? – Squirrel

答えて

1

がOUTERで見つかったのいずれかのレコードが適用されないで、あなたは、currenct断面を示し@ T3に参加し、そこ

からセクションを取得したい場合は、コード

; 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 

内のコメントを参照してください

+0

あなたは天才です!私が実際のデータベースでこれをテストしてみましょう、私はあなたにできるだけ早く戻ってきます。 – KyloRen

+0

これを手伝ってくれてありがとう。一つの質問ですが、私は 'Join 'をあまり使っていません。記録のために、質問は答えられる、私はちょうど将来の参照のために自分自身のために知りたい。 – KyloRen

+0

には、 'INNER JOIN'、' LEFT OUTER JOIN'、 'RIGHT OUTER JOIN'のようないくつかのタイプの' join'があります。基本的には、1つ以上のテーブルを結合するために 'JOIN'を使います。最も一般的なのは 'INNER JOIN'です。さまざまな種類の結合の詳細については、SQLの書籍を検索またはピックアップするだけです。 – Squirrel

関連する問題