繁体   English   中英

结合两个SQL查询?

[英]Combine two SQL queries?

我有两个表Table_1Table_2

我正在使用此SQL语句计算表Info_Data中的Table_1列中特定数据出现了多少次。 以其当前的硬编码形式,它返回的值为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

然后,我还有另一个SQL语句,用于检查Table_2中是否存在Table_2 ,如果不存在,则插入一行并更新数据。 如果确实如此,则只需更新数据即可。

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

这两个语句都按预期工作。

但是我找不到结合这两个语句的方法,我尝试了JOINMERGE没有运气。 作为在第一语句返回的值9 ,我想更换硬编码9在这条线上SET Column_Value = 9Column_Value列值9在这条线VALUES (3201, 2016, 6, 1, 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

您的第一个查询将返回多个列,并且您不能使用它来更新或插入单个列。 相反,使其仅返回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了解更多详细信息。 另请参阅如何从SQL Server中的SELECT更新?

PS单个查询不需要使用BEGIN / END,可以跳过它们。

接受的答案中的两个语句中的冗余使我感到困扰,即对一个业务规则的更改将需要至少在两个位置进行更改。

因此,这是我尝试编写等效的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


可以将其制成具有表值参数的proc来代替上方的params CTE,例如:

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...

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM