Select 来自 table 行匹配列表中位置的所有项目

Select from table rows that match all items in a where in list

我有一个 5 字段 table,我想像这样进行查询:

SELECT *
FROM dbo.table
WHERE somefield in (90,120,30,90)

问题是我在 table 的行中有几个 90、120 和 30 个值,但我只想 return 符合条件的前 4 行。

有什么简单的方法可以做到这一点吗?我在 SQL 服务器 2008.

CREATE TABLE ForgeRock
    ([id] int, [somefield] int)
;

INSERT INTO ForgeRock
    ([id], [somefield])
VALUES
    (1, 90),
    (2, 90),
    (3, 120),
    (4, 30),
    (5, 30),
    (6, 90),
    (7, 10),
    (8, 20),
    (9, 90),
    (10, 30),
    (11, 20)
;

Fidle with data and query。 预期结果将是 90,120,20,90 和他们尊敬的 ids.

您按列表过滤,in 只是检查每个输入值的成员资格。因此,列表中值的顺序位置是什么并不重要,它仅用于过滤。要区分相同值的两个不同实例,您需要将此列表转换为 table 或进行一些其他包含订单信息的转换。

一种方式可以是 table value constructor:

with flt as (
  select
    val,
    row_number() over(partition by val order by val) as rn /*To distinguish instances of the value*/
  from(values (90),(120),(30),(90)) as t(val)
)
, base as (
  select
    f.*,
    row_number() over(partition by somefield order by id) as rn
  from ForgeRock as f
  where somefield in (select flt.val from flt) /*To restrict input before row number*/
)
select b.*
from base as b
  join flt
    /*Match value AND repetition*/
    on b.somefield = flt.val
      and b.rn = flt.rn
id somefield rn
4 30 1
1 90 1
2 90 2
3 120 1

对于现代版本也有 openjson 的可能性,如果您从外部收到此列表:

with flt as (
  select
    [value] as val,
    row_number() over(partition by [value] order by [key]) as rn /*To distinguish instances of the value*/
  from openjson('[90, 120, 30, 90]') as t
)
...
the same code