MySQL ONLY IN() 等效子句

Posted

技术标签:

【中文标题】MySQL ONLY IN() 等效子句【英文标题】:MySQL ONLY IN() equivalent clause 【发布时间】:2013-05-09 12:23:38 【问题描述】:

我在这里给出了我的问题的一个非常抽象的版本,所以请多多包涵。我有一个查询,将检查特定主体是否具有某些相同类型的多个参数。例如,就巧克力而言,男孩有多项选择。但是,我想从桌子上选择与我提到的巧克力完全一样的男孩。不多不少,也不是'LIKE'或'IN()'。

SELECT boy_id from boys_chocolates WHERE chocolate_id ONLY IN('$string');

..当然,'$string' 是一个 php 变量,其中仅包含我想用来拉男孩的巧克力的逗号分隔值。

我知道这是无效的 mysql 语句,但是否有任何有效的等效语句?

编辑:

这是一个更全面的查询,它在特殊情况下获取记录,但并非总是如此。

SELECT boys.* FROM schools_boys INNER JOIN boys ON boys.boy_id=schools_boys.boy_id
INNER JOIN chocolates_boys a ON a.boy_id=boys.boy_id INNER JOIN schools
ON schools.school_id=schools_boys.school_id WHERE a.chocolate_id IN(1000,1003)
AND 
            EXISTS
            (
                    SELECT 1
                    FROM chocolates_boys b
                    WHERE a.boy_id=b.boy_id
                    GROUP BY boy_id
                    HAVING COUNT(DISTINCT chocolate_id) = '2'
                    )

                GROUP BY schools_boys.boy_id HAVING COUNT(*) = '2'

Boys Table
+--------+-------------+
| id     | boy         |
+--------+-------------+
| 10007  | Boy1        |
| 10008  | Boy2        |
| 10009  | Boy3        |
+--------+-------------+

Chocolates Boys Table
+----+---------+--------------+
| id | chocolate_id | boy_id |
+----+--------------+---------+
| 1  | 1000         | 10007   |
| 2  | 1003         | 10007   |
| 3  | 1006         | 10007   |
| 4  | 1000         | 10009   |
| 5  | 1001         | 10009   |
| 6  | 1005         | 10009   |
+----+--------------+---------+

当我单独选择 1000 拉出两个男孩(或)1000 和 1003 拉出 ID 为 10007 的男孩时,没有任何反应。

【问题讨论】:

【参考方案1】:

这个问题叫做Relational Division

SELECT boy_id 
FROM   boys_chocolates 
WHERE  chocolate_id IN ('$string')
GROUP  BY boy_id 
HAVING COUNT(DISTINCT chocolate_id) = ? -- <<== number of chocolates specified

示例:

SELECT boy_id 
FROM   boys_chocolates 
WHERE  chocolate_id IN (1,2,3,4)
GROUP  BY boy_id 
HAVING COUNT(DISTINCT chocolate_id) = 4
SQL of Relational Division

但是,如果 chocolate_id 对于每个 boy_id 都是唯一的,则 DISTINCT 关键字是可选的。

SELECT boy_id 
FROM   boys_chocolates 
WHERE  chocolate_id IN (1,2,3,4)
GROUP  BY boy_id 
HAVING COUNT(*) = 4

更新 1

...我想从桌子上选择那些和我提到的巧克力完全一样的男孩。不多不少……

SELECT boy_id 
FROM   boys_chocolates a
WHERE  chocolate_id IN (1,2,3,4) AND
        EXISTS 
        (
            SELECT  1
            FROM    boys_chocolates b
            WHERE   a.boy_ID = b.boy_ID
            GROUP   BY boy_id
            HAVING  COUNT(DISTINCT chocolate_id) = 4
        )
GROUP  BY boy_id
HAVING COUNT(*) = 4
SQLFiddle Demo

【讨论】:

+1 很好的答案。我认为你应该去掉 WHERE 子句,这样你就不会返回比所需列表中的项目更多的男孩。 实际上这也行不通。我认为您必须添加另一个 HAVING 子句以确保它只是所需的 4。 问题是您将退回任何拥有这 4 个的男孩,无论他们是否有额外的男孩。您应该删除 WHERE 子句并添加第二个 HAVING 子句以避免这种情况。第二个 HAVING 子句可能是(在您的示例中):AND COUNT(DISTINCT CASE WHEN chocolate_id IN (1,2,3,4) THEN chocolate_id ELSE NULL END) = 4 @Tom 好点,我误读了这一行:...exactly the chocolates I mention。原谅我,我会更新答案。 没问题。这是一个很好的答案。只是错过了那一点。

以上是关于MySQL ONLY IN() 等效子句的主要内容,如果未能解决你的问题,请参考以下文章

only_full_group_by : "ORDER BY 子句不在 GROUP BY 子句中"

MYSQL,GROUP BY 子句;这与 sql_mode=only_full_group_by [重复] 不兼容

mysql - 您不能在 FROM 子句中指定要更新的目标表(我的查询有效,但不是等效更新)

MySQL中的空IN子句参数列表

mysql IN子句不使用可能的键

MySQL 视图 OR vs IN 子句