子查询中存在 CASE WHEN 的 SQL 中的奇怪行为(MySQL 5.5)

Posted

技术标签:

【中文标题】子查询中存在 CASE WHEN 的 SQL 中的奇怪行为(MySQL 5.5)【英文标题】:Strange behavior in SQL with CASE WHEN EXIST in subquery (MySQL 5.5) 【发布时间】:2015-04-17 13:37:33 【问题描述】:

我有一家商店,里面有物品和物品组。

我还得到了一些额外的物品,应该从中随机选择一个以将其显示在购物车概览中,如果该物品尚未出现在购物车中。

也可以有项目链接到项目组。如果没有项目链接到购物车中的项目,我想要其中一个,那么购物车内还没有被随机选择

我保存表 item2item 中项目之间的关系:

itemid INT 
additional_item_id INT

我将组和项目之间的关系保存在表 group2item

groupid INT
additional_item_id INT

为了更简单,我们假设我的 item 表如下所示:

itemid INT
name VARCHAR(100)

这是我试图获得的额外物品:

SELECT 
    name 
FROM 
    items a
WHERE 
    (a.itemid) = (
            # if we have any additional items linked to the item get one of em randomly, that is not inside of a cart
            SELECT 
                CASE WHEN EXISTS (
                                    SELECT 
                                        b.additional_item_id 
                                    FROM 
                                        item2item b 
                                    WHERE 
                                        b.additional_item_id NOT IN (10) 
                                        AND b.itemid IN (10)
                                ) 
                        THEN (
                                SELECT 
                                        c.additional_item_id 
                                    FROM 
                                        item2item c 
                                    WHERE 
                                        c.additional_item_id NOT IN (10) 
                                        AND b.itemid IN (10)
                                    ORDER BY 
                                        RAND() 
                                    LIMIT 1
                        # else if we have additional items linked to the items group get one of em randomly, that is not inside of a cart
                        ) ELSE (
                                    (
                                        SELECT 
                                            d.additional_item_id 
                                        FROM 
                                            group2item d 
                                        WHERE 
                                            d.additional_item_id NOT IN (10) 
                                        AND 
                                            d.groupid IN (1) 
                                        ORDER BY RAND() 
                                        LIMIT 1
                                    )
                        ) 
                    END as selecteditemid 
            )

任何人都可以向我解释,为什么我会得到不同数量的行?

【问题讨论】:

【参考方案1】:

您在问为什么您可能会得到不同的行数。以下是一些想法:

items.itemid 不是唯一的,因此重复项来自多个匹配项。 else 子句被执行,where 子句过滤掉所有行。 else 子句被执行,group2item.additional_item_id 不匹配 items.itemid

我推测,当case语句中的第一个条件被执行时,数据可能会在whenthen之间发生变化。

如果您正在寻找解决此问题的方法,请将子查询移至 from 子句,并将更简单的逻辑放在 where 中。

【讨论】:

items.itemid 是主键。我在 item2item 和 group2item 中都有符合指定值的条目。在测试我的 sql 时,我实际上是在使用静态值并且仍然得到不同数量的值......你能举一个例子来说明如何在 from 子句中使用子查询吗?非常感谢您的努力! 顺便说一句。 (a.itemid) = (subquery)

以上是关于子查询中存在 CASE WHEN 的 SQL 中的奇怪行为(MySQL 5.5)的主要内容,如果未能解决你的问题,请参考以下文章

Oracle SQL:对 CASE WHEN 重复使用子查询,而无需重复子查询

使用 case when 时出现 SQL (Redshift) 错误 - 不支持这种类型的相关子查询模式

SQL Server的高级知识

CASE WHEN SQL 查询在 else 中执行条件,即使第一个条件为真

CASE .. Oracle SQL 中的 WHEN 表达式

mysql 查询某个字段并拼接case when出来的字段