3

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

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 

这是表 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       |                |
+--------------+------------------------------------------------------------------------

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

这是表 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. 查询返回结果。有什么区别??应该没有什么区别所以我很困惑

4

1 回答 1

2

简单来说WHERE就是过滤整个结果集JOIN ... ON只过滤连接的表。

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

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


考虑以下简化示例:

表A:

ID
-----
1
2
3

表B:

编号 | 是的
-----+------
1 | 是的
2 | 不
3 | 是的
  1. 一个简单的连接:

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

    返回

    身份证 | B.id | 是的
    -----+------+------
    1 | 1 | 是的
    2 | 2 | 不
    3 | 3 | 是的
    
  2. ON子句中过滤:

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

    返回

    身份证 | B.id | 是的
    -----+------+------
    1 | 1 | 是的
    2 | 空 | 空值
    3 | 3 | 是的
    
  3. WHERE子句中过滤:

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

    返回

    身份证 | B.id | 是的
    -----+------+------
    1 | 1 | 是的
    3 | 3 | 是的
    
于 2013-01-30T06:03:52.463 回答