Mysql Query不会在WHERE上返回结果,而是在AND上返回

时间:2013-01-30 05:56:51

标签: mysql

这是我用来连接两个表的查询

SELECT `rf_popup`.* 
  FROM `rf_popup` LEFT JOIN 
       `g_metadata` ON (`rf_popup`.`name` = `g_metadata`.`name`) 
 WHERE (`g_metadata`.`g_id` = '2009112305475443' AND 
        `g_metadata`.`value` < rf_popup.cardinality OR 
        `g_metadata`.`g_id` IS NULL) AND 
       `category` IN ('S', 'all') AND 
       `field` IN ('descr', 'all') AND 
       `filler_type` IN ('F2', 'all') 
 ORDER BY `rf_popup`.`priority` DESC LIMIT 5 

这是TABLE rf_popup

+--------------+------------------------------------------------------------------------------------+------+-----+---------+----------------+
| Field        | Type                                                                               | Null | Key | Default | Extra          |
+--------------+------------------------------------------------------------------------------------+------+-----+---------+----------------+
| id           | int(11)                                                                            | NO   | PRI | NULL    | auto_increment |
| name         | varchar(200)                                                                       | YES  |     | NULL    |                |
| text         | text                                                                               | YES  |     | NULL    |                |
| cardinality  | int(11)                                                                            | NO   |     | 1       |                |
| field        | varchar(200)                                                                       | YES  |     | NULL    |                |
| category     | enum('A','H','N','R','S','D','all') | YES  |     | NULL    |                |
| time_to_show | enum('START','END')                                                                | YES  |     | START   |                |
| filler_type  | enum('F1','F2','F3','R1','R2','R3','all')   | YES  |     | FILLER1 |                |
| priority     | int(11)                                                                            | NO   |     | 0       |                |
+--------------+------------------------------------------------------------------------

------------ + ------ + ----- + --------- + ----------- ----- +

这是TABLE g_metadata

+-------+--------------+------+-----+---------+----------------+
| Field | Type         | Null | Key | Default | Extra          |
+-------+--------------+------+-----+---------+----------------+
| g_id  | varchar(50)  | YES  | MUL | NULL    |                |
| name  | varchar(50)  | YES  | MUL | NULL    |                |
| value | varchar(200) | YES  |     | NULL    |                |
| id    | int(11)      | NO   | PRI | NULL    | auto_increment |
+-------+--------------+------+-----+---------+----------------+

但是查询返回空结果。但是如果我用WHERE替换查询中的AND。查询返回结果。差异是什么? 应该没有任何区别,所以我很困惑

1 个答案:

答案 0 :(得分:2)

简单来说,WHERE过滤整个结果集JOIN ... ON仅过滤联接的表格。

由于此处有LEFT JOIN,因此将过滤器放在ON子句中会限制为g_metadata表返回的结果,但不会影响为rf_popup返回的结果}。也就是说,您将在连接表(g_metadata)中获得空列,但仍会提取rf_popup的行。

另一方面,将过滤器放在WHERE子句中首先执行连接,然后过滤生成的(连接的)结果集。也就是说,不会返回与整个WHERE子句不匹配的行。


考虑以下简化示例:

TableA:

id
-----
1
2
3

TableB:

id   | yesNo
-----+------
1    | yes
2    | no
3    | yes
  1. 简单加入:

    SELECT * 
    FROM TableA 
    LEFT JOIN TableB ON TableA.id = TableB.id
    

    返回

    A.id | B.id | yesNo
    -----+------+------
    1    | 1    | yes
    2    | 2    | no
    3    | 3    | yes
    
  2. 过滤ON子句:

    SELECT * 
    FROM TableA 
    LEFT JOIN TableB ON TableA.id = TableB.id
        AND yesNo = 'yes'
    

    返回

    A.id | B.id | yesNo
    -----+------+------
    1    | 1    | yes
    2    | NULL | NULL
    3    | 3    | yes
    
  3. 过滤WHERE子句:

    SELECT * 
    FROM TableA 
    LEFT JOIN TableB ON TableA.id = TableB.id
    WHERE yesNo = 'yes'
    

    返回

    A.id | B.id | yesNo
    -----+------+------
    1    | 1    | yes
    3    | 3    | yes