SQL Server 更新语句基于具有多个值的 Select 语句
Posted
技术标签:
【中文标题】SQL Server 更新语句基于具有多个值的 Select 语句【英文标题】:SQL Server update statement based on Select Statement with multiple values 【发布时间】:2020-02-05 22:23:23 【问题描述】:我有一个运行良好的 Select 语句,产生 7636 行:
SELECT c.ClientId
FROM dbo.tblTreatment e
JOIN dbo.tblProgramAssessment pa
ON pa.TreatmentID = e.TreatmentId
JOIN #Client c
ON c.ClientId = e.ClientId
LEFT JOIN dbo.tblCessationOfTreatment ct
ON ct.TreatmentId = e.TreatmentId
LEFT JOIN dbo.tblClientGP m
ON m.ClientId = c.ClientId
WHERE e.IsOpen = 1
AND e.IsDeleted = 0
AND ct.CessationDate is null
AND c.IsDeceased = 0
我正在尝试更新这 7636 行,但它改为更新 7446 行。在我(有限的)理解中,这可能是由于 clientid 的某种原因。这是更新声明:
UPDATE
#Client
SET
ToMigrate = 1
, OpenTreatmentEpisodes = 1
WHERE
clientid in
(SELECT c.ClientId
FROM dbo.tblTreatment e
JOIN dbo.tblProgramAssessment pa
ON pa.TreatmentID = e.TreatmentId
JOIN #Client c
ON c.ClientId = e.ClientId
LEFT JOIN dbo.tblCessationOfTreatment ct
ON ct.TreatmentId = e.TreatmentId
LEFT JOIN dbo.tblClientGP m
ON m.ClientId = c.ClientId
WHERE e.IsOpen = 1
AND e.IsDeleted = 0
AND ct.CessationDate is null
AND c.IsDeceased = 0
)
如果我将“IN”更改为“=”,我会收到一条错误消息: 子查询返回超过 1 个值。当子查询跟随 =、!=、、>= 或子查询用作表达式时,这是不允许的。 声明已终止。
1) 我真的不明白为什么 7446 和 7636 行之间存在差异。 2) 如何只更新 select 语句中的 7636 行?
提前谢谢你!
【问题讨论】:
您的结果表明您在#Client
中有一些重复的 clientid
值
#Client 中重复的 clientid 值是有道理的 - 谢谢@Nick!尽管如此,我如何编写一个 SQL 查询来根据 select 语句只更新 7637 行?
【参考方案1】:
正如 Nick 所说,您可能在表 #Client
中重复了 clientid
。因此,IN
子查询返回的某些元素与外部查询中的几行匹配,导致不需要的行被更新。
我认为您可以通过利用 SQL Server 可更新 CTE 的功能来解决此问题。这可以通过将您的 SELECT
查询转换为 CTE,然后将 UPDATE
直接转换为 CTE 来实现(请注意,要使其正常工作,CTE 必须返回需要更新的列)。
WITH cte AS (
SELECT c.ToMigrate, c.OpenTreatmentEpisodes
FROM dbo.tblTreatment e
INNER JOIN dbo.tblProgramAssessment pa ON pa.TreatmentID = e.TreatmentId
INNER JOIN #Client c ON c.ClientId = e.ClientId
LEFT JOIN dbo.tblCessationOfTreatment ct ON ct.TreatmentId = e.TreatmentId
LEFT JOIN dbo.tblClientGP m ON m.ClientId = c.ClientId
WHERE
e.IsOpen = 1
AND e.IsDeleted = 0
AND ct.CessationDate is null
AND c.IsDeceased = 0
)
UPDATE cte SET ToMigrate = 1, OpenTreatmentEpisodes = 1
【讨论】:
了解@GMB,必须在选择中指定 ToMigrate 和 OpenTreatmentEpisodes。独立执行 Select 语句会产生 7636 行,运行 WITH cte AS (SELECT ..) UPDATE cte Set ToMigrate = 1, OpenTreatmentEpisodes = 1 会产生 7446 行。如果我将“UPDATE cte Set ToMigrate = 1, OpenTreatmentEpisodes = 1”更改为“SELECT * FROM CTE”,它将产生 7636 行。我了解重复 clientid 的可能性,所以我运行了这个:“SELECT COUNT(*),clientid FROM #Client where OpenTreatmentEpisodes = 1 GROUP BY clientid HAVING COUNT(clientid) > 1" (7446 OpenTreatmentEpisodes=1),0 行。 PS - 简单来说,WITH cte 脚本产生 7446 行。以上是关于SQL Server 更新语句基于具有多个值的 Select 语句的主要内容,如果未能解决你的问题,请参考以下文章
ms sql server字符串与另一个具有多个值的字符串进行比较