SQL IN 语句 - 返回结果时保持重复
Posted
技术标签:
【中文标题】SQL IN 语句 - 返回结果时保持重复【英文标题】:SQL IN statement - keep duplicates when returning results 【发布时间】:2015-11-20 20:27:52 【问题描述】:我有一个类似这样的 sql 查询:
SELECT * FROM prices WHERE item IN ('item1', 'item2', 'item2', 'item3');
注意重复值“item2”。 我希望查询返回该项目的值与它在 IN 子句中出现的次数一样多。默认情况下它只返回一次。我该怎么做?
【问题讨论】:
查询正确。这意味着您的prices
表只有一行item2
。要检查,请在表格上执行 count(*)
以查看每个项目有多少行。
IN 子句中无需重复'item2'
。
您要返回哪两个?如果有三个可供选择呢?
【参考方案1】:
那你需要使用left join
:
select p.*
from (select 'item1' as item union all select 'item2' union all
select 'item2' union all select 'item3'
) i left join
prices p
on i.item = p.item;
【讨论】:
您能否从 (1,2,3) 中的商品 UNION ALL 的价格中选择 * 从商品 = 2 的价格中选择 *?【参考方案2】:SQL 将 IN
列表中的项目视为一个集合,忽略重复项。
在支持表值参数 (TVP) 的数据库中,您可以将 IN
替换为 TVP 上的内部联接,但 mysql 不提供它们。
另一种方法是使用您的 IN
列表中的项目填充临时表,并使用内部联接对其进行查询:
CREATE TEMPORARY TABLE InList (item varchar(10));
INSERT INTO InList(item) VALUES ('item1');
INSERT INTO InList(item) VALUES ('item2');
INSERT INTO InList(item) VALUES ('item2');
INSERT INTO InList(item) VALUES ('item3');
现在您的查询将如下所示:
SELECT p.*
FROM prices p
INNER JOIN InList i ON i.item = p.item
由于连接会产生笛卡尔积,price
的行将重复出现在临时 InList
表中列出的次数。
【讨论】:
【参考方案3】:你不能。查询将返回item1
在表中出现的次数,而不是它在您的查询中出现的次数
【讨论】:
【参考方案4】:SELECT *
FROM PRICE
WHERE ITEM IN (item1, item2, item3)
UNION ALL
SELECT *
FROM PRICE
WHERE ITEM = item2
【讨论】:
【参考方案5】:您可以做的一件事是查找每个项目出现的次数,然后检查您想要的次数,如下所示:
SELECT * FROM prices po WHERE
EXISTS (SELECT item FROM prices pi
WHERE pi.item = po.item
GROUP BY item
HAVING ( (COUNT(item) = 1 AND item in ('item1', 'item3') )
OR ( (COUNT(item) = 2 AND item = 'item2' )
)
由于这将返回所有匹配项,因此您将获得每个项目在结果中出现的次数与其在价格表中出现的次数。
关于 Gordon 的回答的两个注释(因为我是新来的,无法在那里发表评论): (1) 左外连接可能导致返回空值。如果 item3 根本没有出现在价格中,那么结果中将出现空值。您可以使用过滤器(其中 p.item 不为空)来删除这些空值。 (2) 如果 item2 在价格表中只出现一次,则连接仍然会使其在结果中出现两次。连接不会检查 item2 在 price 中出现两次,它只是将它两次连接到 FROM 子句中创建的常量表。
【讨论】:
以上是关于SQL IN 语句 - 返回结果时保持重复的主要内容,如果未能解决你的问题,请参考以下文章