You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

当IN(...)子句包含重复值时,如何返回对应重复结果?

解决IN子句无法返回重复匹配项的问题

这事儿我熟!IN子句本身会自动去重,哪怕你写WHERE id IN (1,1,2),数据库也会优化成WHERE id IN (1,2),所以自然不会返回重复结果。要让结果跟着你的输入列表保留重复项,得换个思路——把你的重复值列表转换成一个带重复行的临时数据集,再和原表做JOIN关联就行。

下面给你列几个不同数据库的实现方式,挑你用的来:

通用方案(所有数据库都适用)

用CTE(公共表表达式)构造包含重复值的临时表,再JOIN原表:

WITH target_values AS (
    SELECT 1 AS val UNION ALL  -- 必须用UNION ALL,UNION会去重!
    SELECT 1 AS val UNION ALL
    SELECT 2 AS val
)
SELECT t.*
FROM your_table t
JOIN target_values tv ON t.id = tv.val;

这里核心是UNION ALL,它会保留所有重复行,不像UNION会自动去重。

MySQL/MariaDB 简化写法

直接用VALUES语句快速构造临时数据集:

SELECT t.*
FROM your_table t
JOIN (VALUES (1), (1), (2)) AS tv(val) ON t.id = tv.val;

PostgreSQL 两种写法

除了上面的VALUES方式,还可以用数组展开函数unnest,适合动态传入数组的场景:

-- 方式1:VALUES
SELECT t.*
FROM your_table t
JOIN (VALUES (1), (1), (2)) AS tv(val) ON t.id = tv.val;

-- 方式2:数组展开
SELECT t.*
FROM your_table t
JOIN unnest(ARRAY[1,1,2]) AS tv(val) ON t.id = tv.val;

SQL Server 写法

同样支持VALUES,如果你的重复值是来自字符串(比如'1,1,2'),可以用STRING_SPLIT:

-- 方式1:VALUES
SELECT t.*
FROM your_table t
JOIN (VALUES (1), (1), (2)) AS tv(val) ON t.id = tv.val;

-- 方式2:处理字符串输入
SELECT t.*
FROM your_table t
JOIN STRING_SPLIT('1,1,2', ',') AS tv ON t.id = CAST(tv.value AS INT);

原理说明

IN子句是集合匹配,只关心值是否存在;而JOIN是行匹配,临时数据集里有多少行,就会做多少次匹配。所以只要临时数据集保留了你的重复值,JOIN后就能得到对应次数的结果行。

内容的提问来源于stack exchange,提问作者AnCo ngCo Danh Bun

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.19 08:08:53