简体   繁体   English

结合两个SQL查询?

[英]Combine two SQL queries?

I have two tables, Table_1 and Table_2 . 我有两个表Table_1Table_2

I am using this SQL statement to count how many times a particular piece of data occurs in column Info_Data in Table_1 . 我正在使用此SQL语句计算表Info_Data中的Table_1列中特定数据出现了多少次。 In its current hard coded form it returns a value of 9 以其当前的硬编码形式,它返回的值为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

I then have another SQL statement that checks to see if a row exists in Table_2 , if it does not, insert a row and update the data. 然后,我还有另一个SQL语句,用于检查Table_2中是否存在Table_2 ,如果不存在,则插入一行并更新数据。 If it does ,just update the 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

Both these statements are working how they are supposed to. 这两个语句都按预期工作。

But I can't find a way to combine the two statements, I tried JOIN , MERGE with no luck. 但是我找不到结合这两个语句的方法,我尝试了JOINMERGE没有运气。 Being that the value that the first statement returns is 9 , I want to replace the hard coded 9 on this line SET Column_Value = 9 and the Column_Value columns value 9 on this line VALUES (3201, 2016, 6, 1, 9) with result of the first statement 作为在第一语句返回的值9 ,我想更换硬编码9在这条线上SET Column_Value = 9Column_Value列值9在这条线VALUES (3201, 2016, 6, 1, 9)与结果第一个陈述

This obviously is incorrect, but to illustrate what I am sort of trying to do. 这显然是不正确的,但这只是为了说明我正在尝试做的事情。

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

Your first query returns more than one column and you can't use it to update or insert a single column. 您的第一个查询将返回多个列,并且您不能使用它来更新或插入单个列。 Instead, make it to return only count() and try 相反,使其仅返回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

and

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

As you can see, in INSERT there is no VALUES construction, read http://www.w3schools.com/sql/sql_insert_into_select.asp for more details. 如您所见,在INSERT中没有VALUES构造,请阅读http://www.w3schools.com/sql/sql_insert_into_select.asp了解更多详细信息。 Also see how to How do I UPDATE from a SELECT in SQL Server? 另请参阅如何从SQL Server中的SELECT更新? .

PS Using of BEGIN/END is not required for single queries and they could be skipped. PS单个查询不需要使用BEGIN / END,可以跳过它们。

The redundancy in the two statements in the accepted answer bothers me ie a change to one business rules would need to be changed in at least two places. 接受的答案中的两个语句中的冗余使我感到困扰,即对一个业务规则的更改将需要至少在两个位置进行更改。

So here's my attempt at writing the equivalent MERGE statement (trust you can see the potential for a table-valued parameter here): 因此,这是我尝试编写等效的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 );

I also can't help wondering whether the hard-coded logic of Date_Data BETWEEN '2016/6/1' AND '2016/7/1' in fact relates to the parameter values Year_D = 2016 AND Month_D = 6 . 我也不禁怀疑Date_Data BETWEEN '2016/6/1' AND '2016/7/1'的硬编码逻辑实际上是否与参数值Year_D = 2016 AND Month_D = 6


This could be made into a proc with a table-valued parameter in place of the params CTE above eg something like: 可以将其制成具有表值参数的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