Sql 子查询返回的值超过1,即使使用IN运算符
我的查询很大,但为了理解,我将其粘贴在这里Sql 子查询返回的值超过1,即使使用IN运算符,sql,sql-server,Sql,Sql Server,我的查询很大,但为了理解,我将其粘贴在这里 SELECT DISTINCT ISNULL(CD.InteractionID,'') AS InteractionID , ISNULL(CD.CaseID,'') AS CaseID , ISNULL(CD.AnalysisMonth,'') + '-' + CAST( AnalysisYea
SELECT DISTINCT
ISNULL(CD.InteractionID,'') AS InteractionID
, ISNULL(CD.CaseID,'') AS CaseID
, ISNULL(CD.AnalysisMonth,'') + '-' + CAST( AnalysisYear AS VARCHAR(10)) AS MonYr
, ISNULL(ServiceType,'') AS ServiceType
, ISNULL(ServiceSubType,'') AS ServiceSubType
, ISNULL(SM.SourceName,'') AS SourceName
, ISNULL(UserComment,'') AS UserComment
, ISNULL(Final,'') AS Final
, ISNULL(SYSM.SystemName,'') AS SystemName
, ISNULL(SSM.SubSystem,'') AS SubSystem
, ISNULL(CM.CategoryDesc,'') AS CategoryDesc
, ISNULL(ITCM.ITCommentDesc,'') AS ITCommentDesc
, ISNULL(Casedetails,'') AS Casedetails
, ISNULL(TempRCA,'') AS TempRCA
, ISNULL(FinalRCA,'') AS FinalRCA
, ISNULL(SysOwnerComments ,'') AS SysOwnerComments
FROM
[IT_COMPLAINTS].[ITC_Casedetails] CD WITH (NOLOCK)
INNER JOIN [IT_COMPLAINTS].ITC_SourceMaster SM WITH (NOLOCK) ON CD.SourceID =SM.SourceID
LEFT JOIN [IT_COMPLAINTS].[ITC_SystemMaster] SYSM WITH (NOLOCK) ON CD.SystemID =SYSM.SystemID
LEFT JOIN [IT_COMPLAINTS].[ITC_SubSystemMaster] SSM WITH (NOLOCK) ON CD.SubSystemID=SSM.SubSystemID AND CD.SystemID=SSM.SystemID
LEFT JOIN [IT_COMPLAINTS].[ITC_CategoryMaster] CM WITH (NOLOCK) ON CD.CategoryID =CM.CategoryID
LEFT JOIN [IT_COMPLAINTS].[ITC_ITCommentMaster] ITCM WITH (NOLOCK) ON CD.ITCommentID=ITCM.ITCommentID
INNER JOIN [IT_COMPLAINTS].[ITC_SystemUserMapping] MAP WITH (NOLOCK) ON SSM.SubSystemID = MAP.SubSystemID
WHERE
(IsNull(@InteractionNo,'')='' OR ISNULL(CD.InteractionID,'')=@InteractionNo)
AND (ISNULL(@Mon,'' )='' OR ISNULL(CD.AnalysisMonth,'')=@Mon)
AND (IsNull(@Year,0)=0 OR ISNULL(CD.AnalysisYear,'')=@Year)
--
AND CD.SystemID IN
( CASE WHEN @SystemID = 0 THEN
(SELECT SystemID
FROM IT_COMPLAINTS.ITC_SystemUserMapping
WHERE UserID = @UserID AND IsActive = 1)
ELSE @SystemID END)
AND CD.SubSystemID IN
(CASE WHEN @SystemID = 0 THEN
(SELECT SubSystemID
FROM IT_COMPLAINTS.ITC_SystemUserMapping
WHERE UserID = @UserID AND IsActive = 1)
WHEN @SystemID > 0 AND @SubSystemID = 0 THEN
(SELECT SubSystemID
FROM IT_COMPLAINTS.ITC_SystemUserMapping
WHERE UserID = @UserID AND
IsActive = 1 AND
SystemID = @SystemID)
ELSE @SubSystemID END)
--
AND (ISNULL(@CategoryID,'')='' OR ISNULL(CD.CategoryID,'')=@CategoryID)
AND (ISNULL(@ITCommentID,0)=0 OR ISNULL(CD.ITCommentID,'')=@ITCommentID)
但是,当我运行这个时,它会给我一个错误
子查询返回了多个值。当子查询在=、!=、=或者当子查询用作表达式时
问题在下一部分
AND CD.SystemID IN
( CASE WHEN @SystemID = 0 THEN
(SELECT SystemID
FROM IT_COMPLAINTS.ITC_SystemUserMapping
WHERE UserID = @UserID AND
IsActive = 1) ELSE @SystemID END)
AND CD.SubSystemID IN
(CASE WHEN @SystemID = 0 THEN
(SELECT SubSystemID
FROM IT_COMPLAINTS.ITC_SystemUserMapping
WHERE UserID = @UserID AND
IsActive = 1)
WHEN @SystemID > 0 AND @SubSystemID = 0 THEN
(SELECT SubSystemID
FROM IT_COMPLAINTS.ITC_SystemUserMapping
WHERE UserID = @UserID AND
IsActive = 1 AND
SystemID = @SystemID)
ELSE @SubSystemID END)
当我对此进行评论时,我的查询是有效的,但是这里的子查询和Case有什么问题?就像@zedfoxus评论的一样,问题是这一部分: 。。。然后从IT_COMPLAINTS.ITC_SystemUserMapping中选择SubSystemID 因为如果它返回的值超过1,就没有地方放置该值。您应该将其替换为以下内容:
CD.SubSystemID IN (
SELECT
SubSystemID
FROM
IT_COMPLAINTS.ITC_SystemUserMapping
WHERE
UserID = @UserID AND
IsActive = 1 AND
(
@SystemID = 0 or
(SystemID = @SystemID and @SubSystemID = 0)
)
union all
select @SybSystemID where @SystemID > 0 and @SubSystemID > 0
)
SELECT
UserID, SystemID,
count(*) as "Count",
min(SubSystemID) as minSubSystemID, max(SubSystemID) as maxSubSystemID)
FROM IT_COMPLAINTS.ITC_SystemUserMapping
WHERE IsActive = 1
GROUP BY UserID, SystemID
HAVING COUNT(*) > 1
这可能需要做一些小的调整,但你应该明白这一点
与此相反,您可能希望研究使用if-exists类型的结构。编写起来通常简单得多,性能也更好。在下面的WHERE子句中,您似乎会为SubSystemID WITH和SystemID=@SystemID返回多个值: 与此相反:
FROM
[IT_COMPLAINTS].[ITC_Casedetails] CD WITH (NOLOCK)
...
AND CD.SystemID IN
( CASE WHEN @SystemID = 0 THEN
(SELECT SystemID
FROM IT_COMPLAINTS.ITC_SystemUserMapping
WHERE ...) ELSE @SystemID END)
AND CD.SubSystemID IN
(CASE WHEN @SystemID = 0 THEN
(SELECT SubSystemID
FROM IT_COMPLAINTS.ITC_SystemUserMapping
WHERE ...)
WHEN @SystemID > 0 AND @SubSystemID = 0 THEN
(SELECT SubSystemID
FROM IT_COMPLAINTS.ITC_SystemUserMapping
WHERE ...)
ELSE @SubSystemID END)
考虑CD.SystemID和CD.SubSystemID上的左外部联接表IT_.ITC_SystemUserMapping
比如:
FROM [IT_COMPLAINTS].[ITC_Casedetails] CD WITH (NOLOCK) left outer join
IT_COMPLAINTS.ITC_SystemUserMapping i on
CD.SystemID = @SystemID or
(@SystemID = 0 and
CD.SystemID = SystemID and UserID = @UserID AND IsActive = 1 ) and
CD.SubSystemID = @SubSystemID or
(CD.SubSystemID = SubSystemID and
UserID = @UserID AND IsActive = 1 and
(@SystemID = 0 or
@SystemID > 0 AND SystemID = @SystemID))
您可以通过以下查询识别可能导致问题的用户和系统对:
CD.SubSystemID IN (
SELECT
SubSystemID
FROM
IT_COMPLAINTS.ITC_SystemUserMapping
WHERE
UserID = @UserID AND
IsActive = 1 AND
(
@SystemID = 0 or
(SystemID = @SystemID and @SubSystemID = 0)
)
union all
select @SybSystemID where @SystemID > 0 and @SubSystemID > 0
)
SELECT
UserID, SystemID,
count(*) as "Count",
min(SubSystemID) as minSubSystemID, max(SubSystemID) as maxSubSystemID)
FROM IT_COMPLAINTS.ITC_SystemUserMapping
WHERE IsActive = 1
GROUP BY UserID, SystemID
HAVING COUNT(*) > 1
我同意@JamesZ的回答。如果您不喜欢没有from子句的union和查询,我认为您可以在单个查询中完成
SELECT SubSystemID
FROM IT_COMPLAINTS.ITC_SystemUserMapping
WHERE
UserID = @UserID AND IsActive = 1 AND
(
@SystemID = 0
or SystemID = @SystemID and @SubSystemID = 0
-- assumes that there's a row in this table with this SubSystemID
or SubSystemID = @SubSystemID
)
我不认为您可以在内部使用CASE…在这种情况下,您有多个子查询。其中一个正在返回多个值。请用左联接替换该部分。在x=y和..为什么所有的NOLOCK提示都在这里?您对查询中不准确的结果满意吗?这里的where子句中还有很多不可争论的谓词。您似乎有许多列允许NULL,但您必须不断地将其强制为空字符串。这种事情会扼杀您的性能。您应该能够通过注释3条SELECT语句中的2条来进一步缩小问题范围。其中一个或多个正在返回多个值,这些值可能是相同的。在本例中,它将是且SystemID=0