如何将 UNION 更改为 IN 子句?
Posted
技术标签:
【中文标题】如何将 UNION 更改为 IN 子句?【英文标题】:How to change a UNION to a IN clause? 【发布时间】:2019-07-04 16:37:17 【问题描述】:我需要从同一张表中获取最多 3 条不同的记录,所以目前我正在做:
SELECT 1, mycolumn FROM mytable WHERE id = @firstId
UNION ALL
SELECT 2, mycolumn FROM mytable WHERE id = @secondId
UNION ALL
SELECT 3, mycolumn FROM mytable WHERE id = @thirdId
实际的SELECT
部分包含超过20 列,FROM
部分包含许多JOINs
。第一列是一个常数,并且始终根据记录而固定。我不知道可能会返回多少条记录。可以是 0 到 3 条记录。
是否可以更改上述查询,使其使用IN
,如下所示:
SELECT ???, mycolumn FROM mytable WHERE id IN (@firstId, @secondId, @thirdId)
但是如果我使用IN
,如何将每条记录显式映射到固定常量?
【问题讨论】:
【参考方案1】:您可以在此处将CASE
表达式与单个查询一起使用:
SELECT
CASE id WHEN @firstId THEN 1
WHEN @secondId THEN 2
WHEN @thirdId THEN 3 END AS val,
mycolumn
FROM mytable
WHERE
id IN (@firstId, @secondId, @thirdId);
如果您还希望按计算列排序,请将ORDER BY val
添加到上述查询的末尾。
【讨论】:
ORDER BY val
以确保结果与原始查询相同,或者不需要(@firstId, @secondId, @thirdId
不需要按升序排列)?
@Cid OP的原始查询没有外部order by
,因此它也可以将行返回为3,1,2。
@Cid 好点,但 OP 实际上并没有订购。如果他愿意,OP 可以添加一个ORDER BY
子句。【参考方案2】:
您可以使用CASE
,如下所示。
SELECT
CASE
WHEN id= @firstId THEN 1
WHEN id=@secondId THEN 2
ELSE 3
END AS rn,
mycolumn
FROM mytable
WHERE id IN (@firstId,
@secondId,
@thirdId)
如果您为每个提供的 id 和 @firstId、@secondId 和 @thirdId 按升序排列,则可以使用 DENSE_RANK
的另一种方法。
SELECT DENSE_RANK()
OVER(
ORDER BY id) rn,
mycolumn
FROM mytable
WHERE id IN ( @firstId, @secondId, @thirdId )
【讨论】:
Same thing
- 不,它们是不同的。第二个在编号方面会有空白,就像在 OP 的示例中一样,第一个不会。我假设 OP 正在使用这些数字来识别通过哪个 in
参数找到记录。
我喜欢你的CASE
方法,但如果id
没有以某种方式+1 排序,第一种方法可能不起作用。
Row_number
查询会匹配行吗?例如,如果我只有 @firstId
和 thirdId
的记录,则常量列必须为 1 和 3。
@PSK 还是错了。如果缺少某些行,则需要有间隙。
@TimBiegeleisen,谢谢,我已经相应地更新了描述【参考方案3】:
为此我会推荐一个表值构造函数:
select v.outputnum, my_column
from mytable t join
(values (@firstid, 1),
(@secondid, 2),
(@thirdid, 3)
) v(id, outputnum)
on t.id = v.id
order by v.outputnum;
我认为这比其他版本更简单,因为 id 列表仅在查询中出现一次 - 因此查询的不同部分不同步的危险。
【讨论】:
这肯定是最好的解决方案。 +1以上是关于如何将 UNION 更改为 IN 子句?的主要内容,如果未能解决你的问题,请参考以下文章
SQL Server:如何将 UNION 与两个都有 WHERE 子句的查询一起使用?
如何在 UNION 之间的 SQL 中放置 ORDER BY 子句