2016-07-14 6 views
0

私は2つのテーブルTable_1Table_2を持っています。2つのSQLクエリを結合しますか?

このSQL文を使用して、Info_Dataの特定のデータが何回出現するかを、Table_1にカウントします。現在のハードコード化された形で、それは、行を挿入し、データを更新しない場合、私はその後、行がTable_2に存在するかどうかをチェックし、別のSQLステートメントを有する9

SELECT Staff_No, Info_Data, COUNT(*) cCount 
      FROM Staff_Manager.dbo.Staff_Time_TBL 
      WHERE Staff_No = 3201 AND Date_Data BETWEEN '2016/6/1' AND '2016/7/1' AND Info_Data = 'Data_1' 
      GROUP BY Staff_No, Info_Data 

の値を返します。そうであれば、データを更新するだけです。

IF EXISTS (SELECT * FROM Staff_Manager.dbo.Staff_Count_TBL WHERE Staff_No = 3201 AND Year_D = 2016 AND Month_D = 6 AND Column_Index = 1) 
     BEGIN 
     UPDATE Staff_Manager.dbo.Staff_Count_TBL 
         SET Column_Value = 9 
         WHERE Staff_No = 3201 AND Year_D = 2016 AND Month_D = 6 AND Column_Index = 1 
     END 
    ELSE 
     BEGIN 
     INSERT INTO Staff_Manager.dbo.Staff_Count_TBL (Staff_No, Year_D, Month_D, Column_Index, Column_Value) 
         VALUES (3201, 2016, 6, 1, 9) 
     END 

これらのステートメントは、どのように動作していますか。

しかし、私は2つのステートメントを組み合わせる方法を見つけることができませんでした。私はJOINMERGEを試してみました。 、これは明らかに間違ってい は、最初の文が返す値が9あることなので、私はハードこのラインSET Column_Value = 99コード化された交換したいとColumn_Value列は、最初の文

の結果と、このラインVALUES (3201, 2016, 6, 1, 9)9価値私が何をしようとしているかを説明するためです。

IF EXISTS (SELECT * FROM Staff_Manager.dbo.Staff_Count_TBL WHERE Staff_No = 3201 AND Year_D = 2016 AND Month_D = 6 AND Column_Index = 1) 
BEGIN 
    UPDATE Staff_Manager.dbo.Staff_Count_TBL 
        SET Column_Value = SELECT Staff_No, Info_Data, COUNT(*) cCount 
               FROM Staff_Manager.dbo.Staff_Time_TBL 
               WHERE Staff_No = 3201 AND Date_Data BETWEEN '2016/6/1' AND '2016/7/1' AND Info_Data = 'Data_1' 
               GROUP BY Staff_No, Info_Data 
        WHERE Staff_No = 3201 AND Year_D = 2016 AND Month_D = 6 AND Column_Index = 1 
END 
ELSE 
BEGIN 
    INSERT INTO Staff_Manager.dbo.Staff_Count_TBL (Staff_No, Year_D, Month_D, Column_Index, Column_Value) 
        VALUES (3201, 2016, 6, 1, SELECT Staff_No, Info_Data, COUNT(*) cCount 
               FROM Staff_Manager.dbo.Staff_Time_TBL 
               WHERE Staff_No = 3201 AND Date_Data BETWEEN '2016/6/1' AND '2016/7/1' AND Info_Data = 'Data_1' 
               GROUP BY Staff_No, Info_Data) 
END 

答えて

3

最初のクエリで複数の列が返され、1つの列を更新または挿入するために使用することはできません。代わりに、それだけでcount()を返し、あなたが見ることができるように

UPDATE Staff_Manager.dbo.Staff_Count_TBL 
SET Column_Value = (
    SELECT COUNT(*) 
    FROM Staff_Manager.dbo.Staff_Time_TBL 
    WHERE Staff_No = 3201 AND Date_Data BETWEEN '2016/6/1' AND '2016/7/1' AND Info_Data = 'Data_1' 
    GROUP BY Staff_No, Info_Data 
    ) 
WHERE Staff_No = 3201 AND Year_D = 2016 AND Month_D = 6 AND Column_Index = 1 

INSERT INTO Staff_Manager.dbo.Staff_Count_TBL 
(Staff_No, Year_D, Month_D, Column_Index, Column_Value) 
SELECT 3201, 2016, 6, 1, COUNT(*) 
    FROM Staff_Manager.dbo.Staff_Time_TBL 
    WHERE Staff_No = 3201 AND Date_Data BETWEEN '2016/6/1' AND '2016/7/1' AND Info_Data = 'Data_1' 
    GROUP BY Staff_No, Info_Data 

を試して作る、INSERTに何のVALUESの建設はありません、詳細についてはhttp://www.w3schools.com/sql/sql_insert_into_select.aspをお読みください。 How do I UPDATE from a SELECT in SQL Server?も参照してください。

P.S. BEGIN/ENDの使用は、単一の照会には必要なく、スキップすることができます。

+0

ああ、私はあなたが何を意味するかを見ます。素晴らしい作品をありがとう。 – KyloRen

1

受け入れられた回答の2つのステートメントの冗長性によって、1つのビジネスルールの変更を少なくとも2か所で変更する必要があります。だからここ

は(あなたがここにテーブル値パラメータの可能性を見ることができます信頼)と同等MERGE文を書く時私の試みです:

WITH Params AS 
(
SELECT * 
    FROM (VALUES (3201, 2016, 6, 1)) 
     AS T (Staff_No, Year_D, Month_D, Column_Index) 
), 
ParamsWithCount AS 
(
SELECT p.Staff_No, p.Year_D, p.Month_D, p.Column_Index, COUNT(*) AS Column_Value 
    FROM Params p 
     JOIN Staff_Manager.dbo.Staff_Time_TBL t 
      ON p.Staff_No = t.Staff_No 
    WHERE t.Date_Data BETWEEN '2016/6/1' AND '2016/7/1' 
     AND t.Info_Data = 'Data_1' 
    GROUP 
    BY p.Staff_No, p.Year_D, p.Month_D, p.Column_Index, t.Info_Data 
) 
MERGE Staff_Manager.dbo.Staff_Count_TBL t 
    USING ParamsWithCount p 
     ON t.Staff_No = p.Staff_No 
     AND t.Year_D = p.Year_D 
     AND t.Month_D = p.Month_D 
     AND t.Column_Index = p.Column_Index 
WHEN MATCHED THEN 
    UPDATE 
     SET Column_Value = p.Column_Value 
WHEN NOT MATCHED THEN 
    INSERT (Staff_No, Year_D, Month_D, Column_Index, Column_Value) 
     VALUES (p.Staff_No, p.Year_D, p.Month_D, p.Column_Index, p.Column_Value); 

私もハードコーディングされたロジックかどうかを疑問に役立つことはできません実際、Date_Data BETWEEN '2016/6/1' AND '2016/7/1'のパラメータ値は、パラメータ値Year_D = 2016 AND Month_D = 6に関連しています。


これは、例えば上記params CTEの代わりにテーブル値パラメータとPROCに作ることができます次のようなもの:

CREATE TYPE Staff_Count_Type AS TABLE 
(
Staff_No INT, 
Year_D INT, 
Month_D INT, 
Column_Index INT 
); 

CREATE PROCEDURE UpateOrCreateStaffCount 
@params Staff_Count_Type READONLY 
AS 
WITH ParamsWithCount AS 
(
SELECT p.Staff_No, p.Year_D, p.Month_D, p.Column_Index, COUNT(*) AS Column_Value 
    FROM @params p 
     JOIN Staff_Manager.dbo.Staff_Time_TBL ...snipped... 
+0

お時間をいただきありがとうございます。はい、ハードコーディングされた月と年は日付にdirrectly相関します。これをC#に入れると、ハードコードされたデータはまったくありません。私はあなたが 'table-valued parameter'をどういう意味にしているのか、私は確信していません。もう一度おねがいします。助けと素敵な答えに投票してください。ところで、素晴らしい作品です。 – KyloRen

+0

テーブル値のパラメータを持つprocの概要で更新されました。 – onedaywhen

関連する問題