SQL 使用带合并的 IN 语句的子查询
SQL Subquery using IN Statment with coalesce
我有以下SELECT声明
SELECT
UserID
,UserName
,TradingParty
,Email
,[PrivDesc]
,LastLogin
,IsApproved
FROM
cte_getAll allUsers
WHERE
allUsers.TradingParty = COALESCE(@TradingParty, allUsers.TradingParty)
AND allUsers.Username = COALESCE(@Username, allUsers.Username)
AND allUsers.Email = COALESCE(@EmailAddress, allUsers.Email)
AND DATEADD(dd, DATEDIFF(dd, 0, allUsers.[LastLogin]), 0) >= COALESCE(@FromDate, DATEADD(dd, DATEDIFF(dd, 0, allUsers.[LastLogin]), 0))
AND DATEADD(dd, DATEDIFF(dd, 0, allUsers.[LastLogin]), 0) <= COALESCE( @ToDate, DATEADD(dd, DATEDIFF(dd, 0, allUsers.[LastLogin]), 0))
AND allUsers.IsApproved = COALESCE(@AccountActive, allUsers.IsApproved)
AND allUsers.[PrivId] -- IN (SELECT privId from @selectedPriv)
IN (COALESCE((SELECT PrivID FROM @selectedPriv), allUsers.[PrivId]))
编辑
在此声明之前,我根据用户输入填充@selectedPriv temp table。如果没有用户输入,那么 table 将不包含任何内容
在最后的 AND 语句中,我试图找到 privId 等于用户输入的 privs 列表的所有数据。因此,例如,用户输入存储在临时 table 中的 1、2、3、4、5、6,我需要从中找到与我的原始 table 相关联的所有行这些私人。
如果我使用注释的 IN 语句,这是我的问题,但由于允许用户传入 NULL,我需要在 COALESCE 中使用它,但是当我这样做时,我收到消息
Subquery returned more than 1 value. This is not permitted when the
subquery follows =, !=, <, <= , >, >= or when the subquery is used as
an expression.
我不知道这是为什么。有什么想法可以帮助我解决这个问题吗?
由于您要在该语句之前填充临时 table @selectedPriv,只需在此处添加一个 else - 如果输入为空,则具有 @selectedPriv =
SELECT DISTINCT PrivId FROM cte_getAll
这应该比在 @selectedPriv 中检查 count(*) 的更复杂的 where 语句更快,这是另一种方法。
COALESCE 的第一个参数只能取一个值,这就是为什么当您从该查询中获得多个值时它会报错。您可以使用一些 AND 和 OR 将该部分切换为有点不同的东西。 (注意:未经测试,但至少应该接近。)
AND (((select count(*) from @selectedPriv) = 0)
OR ((select count(*) from @selectedPriv) != 0 AND allUsers.[PrivId] IN (SELECT privId from @selectedPriv)))
如果我对你的问题的理解正确,你有一个 table 变量,它具有你想要 select 来自的值,但如果它们在 table, 你根本不需要限制。
您收到错误的原因是 COALESCE()
只希望转换一个值,但您的查询返回多个值。
这可能是您要找的:
AND
(
NOT EXISTS (SELECT * FROM @selectedPriv WHERE PrivID IS NOT NULL)
OR
(
EXISTS (SELECT * FROM @selectedPriv WHERE PrivID IS NOT NULL)
AND allUsers.[PrivId] IN (SELECT PrivID FROM @selectedPriv)
)
)
合并工作正常,但您可以改用 OR,这可能会帮助您完成最后的 AND。
SELECT
UserID,
UserName,
TradingParty,
Email,
[PrivDesc],
LastLogin,
IsApproved
FROM
cte_getAll allUsers
WHERE
allUsers.TradingParty = COALESCE(@TradingParty,allUsers.TradingParty)
AND (@Username IS NULL OR allUsers.Username = @Username)
AND (@EmailAddress IS NULL OR allUsers.Email = @EmailAddress)
AND (@FromDate IS NULL OR DATEADD(dd,DATEDIFF(dd,0,allUsers.[LastLogin]),0) >= @FromDate)
AND (@ToDate IS NULL OR DATEADD(dd,DATEDIFF(dd,0,allUsers.[LastLogin]),0) <= @ToDate)
AND (@AccountActive IS NULL OR allUsers.IsApproved = @AccountActive)
AND (@PrivIDS IS NULL OR allUsers.[PrivId] IN (SELECT PrivID FROM @selectedPriv))
我有以下SELECT声明
SELECT
UserID
,UserName
,TradingParty
,Email
,[PrivDesc]
,LastLogin
,IsApproved
FROM
cte_getAll allUsers
WHERE
allUsers.TradingParty = COALESCE(@TradingParty, allUsers.TradingParty)
AND allUsers.Username = COALESCE(@Username, allUsers.Username)
AND allUsers.Email = COALESCE(@EmailAddress, allUsers.Email)
AND DATEADD(dd, DATEDIFF(dd, 0, allUsers.[LastLogin]), 0) >= COALESCE(@FromDate, DATEADD(dd, DATEDIFF(dd, 0, allUsers.[LastLogin]), 0))
AND DATEADD(dd, DATEDIFF(dd, 0, allUsers.[LastLogin]), 0) <= COALESCE( @ToDate, DATEADD(dd, DATEDIFF(dd, 0, allUsers.[LastLogin]), 0))
AND allUsers.IsApproved = COALESCE(@AccountActive, allUsers.IsApproved)
AND allUsers.[PrivId] -- IN (SELECT privId from @selectedPriv)
IN (COALESCE((SELECT PrivID FROM @selectedPriv), allUsers.[PrivId]))
编辑 在此声明之前,我根据用户输入填充@selectedPriv temp table。如果没有用户输入,那么 table 将不包含任何内容
在最后的 AND 语句中,我试图找到 privId 等于用户输入的 privs 列表的所有数据。因此,例如,用户输入存储在临时 table 中的 1、2、3、4、5、6,我需要从中找到与我的原始 table 相关联的所有行这些私人。 如果我使用注释的 IN 语句,这是我的问题,但由于允许用户传入 NULL,我需要在 COALESCE 中使用它,但是当我这样做时,我收到消息
Subquery returned more than 1 value. This is not permitted when the subquery follows =, !=, <, <= , >, >= or when the subquery is used as an expression.
我不知道这是为什么。有什么想法可以帮助我解决这个问题吗?
由于您要在该语句之前填充临时 table @selectedPriv,只需在此处添加一个 else - 如果输入为空,则具有 @selectedPriv =
SELECT DISTINCT PrivId FROM cte_getAll
这应该比在 @selectedPriv 中检查 count(*) 的更复杂的 where 语句更快,这是另一种方法。
COALESCE 的第一个参数只能取一个值,这就是为什么当您从该查询中获得多个值时它会报错。您可以使用一些 AND 和 OR 将该部分切换为有点不同的东西。 (注意:未经测试,但至少应该接近。)
AND (((select count(*) from @selectedPriv) = 0)
OR ((select count(*) from @selectedPriv) != 0 AND allUsers.[PrivId] IN (SELECT privId from @selectedPriv)))
如果我对你的问题的理解正确,你有一个 table 变量,它具有你想要 select 来自的值,但如果它们在 table, 你根本不需要限制。
您收到错误的原因是 COALESCE()
只希望转换一个值,但您的查询返回多个值。
这可能是您要找的:
AND
(
NOT EXISTS (SELECT * FROM @selectedPriv WHERE PrivID IS NOT NULL)
OR
(
EXISTS (SELECT * FROM @selectedPriv WHERE PrivID IS NOT NULL)
AND allUsers.[PrivId] IN (SELECT PrivID FROM @selectedPriv)
)
)
合并工作正常,但您可以改用 OR,这可能会帮助您完成最后的 AND。
SELECT
UserID,
UserName,
TradingParty,
Email,
[PrivDesc],
LastLogin,
IsApproved
FROM
cte_getAll allUsers
WHERE
allUsers.TradingParty = COALESCE(@TradingParty,allUsers.TradingParty)
AND (@Username IS NULL OR allUsers.Username = @Username)
AND (@EmailAddress IS NULL OR allUsers.Email = @EmailAddress)
AND (@FromDate IS NULL OR DATEADD(dd,DATEDIFF(dd,0,allUsers.[LastLogin]),0) >= @FromDate)
AND (@ToDate IS NULL OR DATEADD(dd,DATEDIFF(dd,0,allUsers.[LastLogin]),0) <= @ToDate)
AND (@AccountActive IS NULL OR allUsers.IsApproved = @AccountActive)
AND (@PrivIDS IS NULL OR allUsers.[PrivId] IN (SELECT PrivID FROM @selectedPriv))