Tsql SQL-通过SELECT的结果集向上插入循环

Tsql SQL-通过SELECT的结果集向上插入循环,tsql,sql-server-2016,Tsql,Sql Server 2016,我有一个从表a和表b返回两列数据UserID和ServiceID的查询 上述查询返回以下数据集: 我需要按以下方式向上插入表c: 若表c中存在UserID和ServiceID,则从表c中获取调度列的当前值并添加1 如果表c中不存在UserID和ServiceID,则使用上述select语句中选择的UserID和ServiceID将记录插入表c,并将1添加到计划列中 我的问题是如何对select语句返回的每一行执行此操作,以确保所有结果都上传到表c中 我正在通过循环案例或if-else语句寻找可能

我有一个从表a和表b返回两列数据UserID和ServiceID的查询

上述查询返回以下数据集:

我需要按以下方式向上插入表c: 若表c中存在UserID和ServiceID,则从表c中获取调度列的当前值并添加1

如果表c中不存在UserID和ServiceID,则使用上述select语句中选择的UserID和ServiceID将记录插入表c,并将1添加到计划列中

我的问题是如何对select语句返回的每一行执行此操作,以确保所有结果都上传到表c中

我正在通过循环案例或if-else语句寻找可能的解决方案,但任何输入都是非常感谢的

我的上述尝试:

IF EXISTS (SELECT sa.UserID as S_UserID, ce.ServiceID as S_ServiceID FROM TableA a
JOIN TableB b
ON b.EventID = a.EventID
WHERE a.EventID = 1892286
AND a.Attendance IN (1,2))
UPDATE TableC c
SET
UserID = S_UserID
ServiceID = S_ServiceID
Scheduled = Scheduled + 1
WHERE UserID = S_UserID
AND ServiceID = S_ServiceID
ELSE
INSERT INTO TableC
(UserID,ServiceID,Scheduled)
VALUES
(S_UserID,S_ServiceID,1)
END

一种方法是执行不同的语句来插入和更新

-- INSERT INTO Temporary Table
SELECT  sa.UserID, 
        ce.ServiceID 
INTO    #tempC
FROM    TableA a
        JOIN TableB b ON b.EventID = a.EventID
WHERE   a.EventID = 1892286
        AND a.Attendance IN (1,2)

-- UPDATE Existing ROWS
UPDATE  c
SET     c.Scheduled = c.Scheduled + 1
FROM    #tempC c
        INNER JOIN TableC d
            ON c.UserID = d.UserID
                AND c.ServiceID = d.ServiceID

-- INSERT new rows
INSERT INTO TableC (UserID, ServiceID,Scheduled)
SELECT  c.UserID, c.ServiceID, 1
FROM    #tempC c
        LEFT JOIN TableC d
            ON c.UserID = d.UserID
                AND c.ServiceID = d.ServiceID
WHERE   d.UserID IS NULL

-- DROP temporary table
DROP TABLE #tempC

一种方法是执行不同的语句来插入和更新

-- INSERT INTO Temporary Table
SELECT  sa.UserID, 
        ce.ServiceID 
INTO    #tempC
FROM    TableA a
        JOIN TableB b ON b.EventID = a.EventID
WHERE   a.EventID = 1892286
        AND a.Attendance IN (1,2)

-- UPDATE Existing ROWS
UPDATE  c
SET     c.Scheduled = c.Scheduled + 1
FROM    #tempC c
        INNER JOIN TableC d
            ON c.UserID = d.UserID
                AND c.ServiceID = d.ServiceID

-- INSERT new rows
INSERT INTO TableC (UserID, ServiceID,Scheduled)
SELECT  c.UserID, c.ServiceID, 1
FROM    #tempC c
        LEFT JOIN TableC d
            ON c.UserID = d.UserID
                AND c.ServiceID = d.ServiceID
WHERE   d.UserID IS NULL

-- DROP temporary table
DROP TABLE #tempC

如果您使用的是较新版本的SQL Server,则此问题标记为SQL-Server-2016,然后您可以使用MERGE语句

根据您的帖子,这里有一个稍微简化的示例:

--create test tables
CREATE TABLE #a (UserID int);
CREATE TABLE #b (UserID int, ServiceID int);
CREATE TABLE #c (UserID int, ServiceID int, Scheduled int);

--insert some data matching the question
INSERT INTO #a
VALUES(1), (2), (3), (4), (5);

INSERT INTO #b
VALUES (1, 33), (2, 44), (3, 55)

INSERT INTO #c
VALUES(2, 44, 3), (4, 66, 1)

--ensure we have data
SELECT * FROM #a
SELECT * FROM #b
SELECT * FROM #c

--use the MERGE statement
MERGE #c AS tgt
USING(SELECT a.UserID, b.ServiceID FROM #a a JOIN #b b ON a.UserID = b.UserID) src
ON (tgt.UserID = src.UserID AND tgt.ServiceID = src.ServiceID)
WHEN NOT MATCHED THEN
  INSERT (UserID, ServiceID, Scheduled)
  VALUES(src.UserID, src.ServiceID, 1)
WHEN MATCHED THEN
  UPDATE 
    SET Scheduled += 1;

--check what's been inserted/updated
SELECT * FROM #c
请注意,合并有时会影响性能,因此请谨慎使用。有关合并的详细信息


希望这有帮助

如果您使用的是较新版本的SQL Server,则此问题标记为SQL-Server-2016,然后您可以使用MERGE语句

根据您的帖子,这里有一个稍微简化的示例:

--create test tables
CREATE TABLE #a (UserID int);
CREATE TABLE #b (UserID int, ServiceID int);
CREATE TABLE #c (UserID int, ServiceID int, Scheduled int);

--insert some data matching the question
INSERT INTO #a
VALUES(1), (2), (3), (4), (5);

INSERT INTO #b
VALUES (1, 33), (2, 44), (3, 55)

INSERT INTO #c
VALUES(2, 44, 3), (4, 66, 1)

--ensure we have data
SELECT * FROM #a
SELECT * FROM #b
SELECT * FROM #c

--use the MERGE statement
MERGE #c AS tgt
USING(SELECT a.UserID, b.ServiceID FROM #a a JOIN #b b ON a.UserID = b.UserID) src
ON (tgt.UserID = src.UserID AND tgt.ServiceID = src.ServiceID)
WHEN NOT MATCHED THEN
  INSERT (UserID, ServiceID, Scheduled)
  VALUES(src.UserID, src.ServiceID, 1)
WHEN MATCHED THEN
  UPDATE 
    SET Scheduled += 1;

--check what's been inserted/updated
SELECT * FROM #c
请注意,合并有时会影响性能,因此请谨慎使用。有关合并的详细信息


希望这有帮助

循环是无效的

ca和ce不是有效的别名,因此我必须猜测有效的别名

从备份开始,以防出错

update c 
   set c.serviceID = c.serviceID + 1  
  FROM TableA a
  JOIN TableB b
    ON b.EventID = a.EventID
   and a.EventID = 1892286
   AND a.Attendance IN (1,2) 
  join TableC c 
    on c.UserID = a.UserID 
   and c.ServiceID = b.ServiceID; 

INSERT INTO TableC (UserID, ServiceID, Scheduled)
SELECT a.UserID, b.ServiceID, 1 
  FROM TableA a
  JOIN TableB b
    ON b.EventID = a.EventID
   and a.EventID = 1892286
   AND a.Attendance IN (1,2)  
 where not exists (select 1 
                     from TableC c 
                    where c.UserID = a.UserID 
                      and c.ServiceID = b.ServiceID 
                  );

循环是无效的

ca和ce不是有效的别名,因此我必须猜测有效的别名

从备份开始,以防出错

update c 
   set c.serviceID = c.serviceID + 1  
  FROM TableA a
  JOIN TableB b
    ON b.EventID = a.EventID
   and a.EventID = 1892286
   AND a.Attendance IN (1,2) 
  join TableC c 
    on c.UserID = a.UserID 
   and c.ServiceID = b.ServiceID; 

INSERT INTO TableC (UserID, ServiceID, Scheduled)
SELECT a.UserID, b.ServiceID, 1 
  FROM TableA a
  JOIN TableB b
    ON b.EventID = a.EventID
   and a.EventID = 1892286
   AND a.Attendance IN (1,2)  
 where not exists (select 1 
                     from TableC c 
                    where c.UserID = a.UserID 
                      and c.ServiceID = b.ServiceID 
                  );

在本例中,我们与更新与插入有何区别?在这种情况下,我看到这两种方法都起作用。它们所使用的联接类型不同。第一个使用内部联接,它将获取现有记录,而第二个使用左联接获取不存在的行。在本例中,我们与更新与插入有什么区别?在这种情况下,我看到这两种方法都起作用。它们所使用的联接类型不同。第一个使用内部联接,该联接将获取现有记录,而第二个使用左联接获取不存在的行。未为sa或ce定义别名。“这些都不是有效的语法。@狗仔队是的,我对我的原始代码做了一些修改,以将其推广到stackoverflow,我忽略了这些别名。感谢大家提供的示例,我将尝试所有这些示例,看看哪种最适合我的实现,并相应地接受它们question@Paparazzi为sa或ce定义的所有doneNo别名。“这些都不是有效的语法。@狗仔队是的,我对我的原始代码做了一些修改,以将其推广到stackoverflow,我忽略了这些别名。感谢大家提供的示例,我将尝试所有这些示例,看看哪种最适合我的实现,并相应地接受它们question@Paparazzi所有这些都是doneNice示例,但我认为分成两个语句是一种更好的方法。@Niels Berglund,谢谢你的示例!在过去,我曾研究过使用MERGE,我唯一关心的是,每当某个特定的EVENTID的一个位字段被切换为true时,我都会执行这个查询,并且只希望根据与该EVENTID直接相关的记录来更新/插入数据。似乎使用merge只会匹配两个表中的数据,而不会计算特定的记录,因为只有theresnotwhere语句。可以修改为包含一个事件ID并只触发与给定eventID的某些参数匹配的数据吗?嗨,当然-在使用部分和不匹配时可以有一个WHERE子句。这是一个很好的例子,但我认为拆分为两个语句是一种更好的方法。@Niels Berglund,感谢您提供了这个例子!在过去,我曾研究过使用MERGE,我唯一关心的是,每当某个特定的EVENTID的一个位字段被切换为true时,我都会执行这个查询,并且只希望根据与该EVENTID直接相关的记录来更新/插入数据。似乎使用merge只会匹配两个表中的数据,而不会计算特定的记录,因为只有theresnotwhere语句。是否可以修改为包含一个事件ID和仅与给定eventID的某些参数匹配的触发器数据?您好,当然可以-您可以在使用部分和不匹配时在中使用WHERE子句。