如何将 UNION 更改为 IN 子句?

How to change a UNION to a IN clause?

我需要从同一个 table 中获取最多 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。第一列是常量,始终根据记录固定。我不知道有多少条记录可能 return。它可以是 0 到 3 条记录。

是否可以更改上述查询,使其使用 IN,如下所示:

SELECT ???, mycolumn FROM mytable WHERE id IN (@firstId, @secondId, @thirdId)

但是,如果我使用 IN,如何将每条记录显式映射到固定常量?

您可以像下面这样使用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)

另一种方法可以使用 DENSE_RANK 如果每个提供的 ID 都有一个记录,并且 @firstId、@secondId 和 @thirdId 是按升序排列的。

SELECT DENSE_RANK() 
         OVER( 
           ORDER BY id) rn, 
       mycolumn 
FROM   mytable 
WHERE  id IN ( @firstId, @secondId, @thirdId ) 

您可以在此处对单个查询使用 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 添加到上述查询的末尾。

为此,我建议使用 table 值的构造函数:

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 列表在查询中只出现一次——因此不会有查询的不同部分不同步的危险。