为什么这个简单的Left Join从不匹配的行返回数据?

use*_*566 7 mysql sql left-join

有关此问题的操作,请参阅简单的http://sqlfiddle.com/#!9/e853f/1.

我指的是MySQL ver 5.6.12-log

据我了解,左连接为最右侧数据集中的列返回NULL,其中左侧数据集中的键不存在于右侧数据集中.

但是,即使左侧不存在左手键,我也会从右侧返回数据.

谁能解释一下这里发生了什么?

SQLfiddle创建:

  • 一个包含6行的表,每行只包含一个整数ID
  • 第二个表包含3行,其中包含一些整数ID以及另外两个INT字段
  • 基于该第二个表的视图,该表返回包含整数ID的3行以及从其他两个INT字段派生的文本字段

(显然,视图中的3个ID对应于6行表中的一些ID.)

SQL SELECT*FROM LEFT JOIN ON table_ID = view_ID; 按预期返回6行,但所有这些行都在文本字段中有数据,而不是3个不匹配的数据为NULL

如果视图中用于派生文本列的方法稍有改动,那么Left Join SQL会给出正确的结果. (您可以通过选择性地在sql小提琴中注释掉两个方法中的一个或另一个来显示这个)

但是肯定不是优化器首先评估视图,所以数据的创建方式和它包含的内容无关紧要?

(我承认的早期问题的这个简化版本对于非法合理的答案来说太复杂了)

有人建议(Jeroen Mostert)我展示数据和预期结果.这里是:

表人

personID
--------
   1
   2
   3
   4
   5
   6
Run Code Online (Sandbox Code Playgroud)

查看payment_state

payment_personID  |   state
----------------------------
       1          |   'equal'
       2          |   'under'
       3          |   'over'
Run Code Online (Sandbox Code Playgroud)

询问

SELECT * FROM  person 
LEFT JOIN   payment_state 
ON personID = payment_personID;
Run Code Online (Sandbox Code Playgroud)

预期结果

personID | payment_personID  |state
-------------------------------------
    1    |      1            | 'equal'
    2    |      2            | 'under'
    3    |      3            | 'over'
    4    |     NULL          |  NULL
    5    |     NULL          |  NULL
    6    |     NULL          |  NULL
Run Code Online (Sandbox Code Playgroud)

实际结果

personID | payment_personID  |state
-------------------------------------
    1    |      1            | 'equal'
    2    |      2            | 'under'
    3    |      3            | 'over'
    4    |     NULL          | 'equal'
    5    |     NULL          | 'equal'
    6    |     NULL          | 'equal'
Run Code Online (Sandbox Code Playgroud)

Pel*_*lin 1

您的视图的处理算法会导致此结果。默认情况下,MySQL通常选择MERGE,因为它更高效。如果您使用“TEMPTABLE”算法创建视图,您将能够看到不匹配行的 NULL。

http://www.mysqltutorial.org/create-sql-views-mysql.aspx

CREATE ALGORITHM =  TEMPTABLE VIEW  payment_state AS (
SELECT
   payment_personID,
 CASE 
   WHEN IFNULL(paid,0) < IFNULL(due,0) AND due <> 0 THEN 'under' 
   WHEN IFNULL(paid,0) > IFNULL(due,0) THEN 'over' 
   WHEN IFNULL(paid,0) = IFNULL(due,0) THEN 'equal' 
   END AS state 
FROM payments);
Run Code Online (Sandbox Code Playgroud)