如何JOIN多个表并返回NULL值的结果

时间:2013-07-25 21:45:13

标签: mysql

我正在尝试连接4个表,其中一个表没有所有匹配的ID但是我仍然需要显示连接的结果,甚至是没有相应ID的行。

这是我正在谈论的一个例子:

示例表:


    DECLARE @Table1 TABLE (id INT PRIMARY KEY CLUSTERED, ts DateTime, tbl2_id INT, price DECIMAL(4,2), tbl3_id INT, tbl4_id INT)

    INSERT INTO @Table1 VALUES(1, '2013-07-25 09:30:00', 10, 10.25, 1);
    INSERT INTO @Table1 VALUES(2, '2013-07-25 10:25:00', 20, 25.25, 1);
    INSERT INTO @Table1 VALUES(3, '2013-07-25 11:45:00', 30, 30.15, 2);
    INSERT INTO @Table1 VALUES(4, '2013-07-25 13:31:00', 40, 80.40, 2);

    DECLARE @Table2 TABLE (id INT PRIMARY KEY CLUSTERED, symbol VARCHAR(25), tbl1_id int)

    INSERT INTO @Table2 VALUES(10, 'XYZ', 1);
    INSERT INTO @Table2 VALUES(20, 'ABC', 2);
    INSERT INTO @Table2 VALUES(30, 'RST', 3);
    INSERT INTO @Table2 VALUES(40, 'EFG', 4);

    DECLARE @Table3 TABLE (id INT PRIMARY KEY CLUSTERED, exch VARCHAR(25))

    INSERT INTO @Table3 VALUES(1, 'A');
    INSERT INTO @Table3 VALUES(2, 'B');
    INSERT INTO @Table3 VALUES(3, 'C');
    INSERT INTO @Table3 VALUES(4, 'D');

    DECLARE @Table4 TABLE (id INT PRIMARY KEY CLUSTERED, int tbl1_id, cnt INT)

    INSERT INTO @Table4 VALUES(1, 2, 19);
    INSERT INTO @Table4 VALUES(2, 4, 2013);

示例查询:

    SELECT tbl1.id, tbl1.ts, tbl2.symbol, IFNULL(tbl3.cnt,0) AS cnt

    FROM TABLE1 tbl1

    JOIN TABLE2 tbl2
    ON tbl1.tbl2_id = tbl2.id

    JOIN TABLE3 tbl3
    ON tbl3.id = tbl1.tbl3_id

    LEFT OUTER JOIN TABLE4 tbl4
    ON tbl1.tbl4_id = tbl4.id

    WHERE tbl1.ts BETWEEN '2013-07-25 09:30:00 AND '2013-07-25 16:00:00'
    AND tbl1.price >= 15.00
    LIMIT 1000;

所以基本上我要做的是如果tbl4没有tbl1_id我仍然希望看到来自table1的结果但是为Cnt显示0值...当我运行这个查询时我是得到一堆重复的条目,数据看起来不正确。

2 个答案:

答案 0 :(得分:1)

您只返回来自联接左侧的匹配项。将表4的连接更改为右连接,它将返回右侧的所有记录,无论如何。我知道这是一个不能与假数据一起使用的示例查询。但我必须与你给我的东西一起工作。这可能不会通过复制和粘贴工作,但理论是正确的,你只需要修改它。如果您提供更详细的信息,我会根据它进行定制。

SELECT tbl1.id, tbl1.ts, tbl2.symbol, IFNULL(tbl3.cnt,0) AS cnt

    FROM TABLE1 tbl1

    JOIN TABLE2 tbl2
    ON tbl1.tbl2_id = tbl2.id

    JOIN TABLE3 tbl3
    ON tbl3.id = tbl1.tbl3_id

    RIGHT JOIN TABLE4 tbl4
    ON tbl1.tbl4_id = tbl4.id

    WHERE tbl1.ts BETWEEN '2013-07-25 09:30:00 AND '2013-07-25 16:00:00'
    AND tbl1.price >= 15.00
    LIMIT 1000;

答案 1 :(得分:0)

首先在您的示例代码中,您混合使用了SQL Server和MySql语法:

  • DECLARE TABLECLUSTERED是SQL Server功能
  • IFNULL()LIMIT是MySql的

其次 cnt列在表4中而非表3中,因此IFNULL(tbl3.cnt,0)不会飞。

第三次当您将tbl1.id = tbl4.tbl1_id更改为tbl1.tbl4_id = tbl4.id时,您的上一次修改不会与其他示例数据相加,因为您的插入中没有值tbl3_id或新引入的tbl4_id语句。现在似乎没有tbl1_id列。

因此恕我直言,您需要重新访问并更正您的样本数据。发布所需的输出也可以帮助您获得答案。


现在,这是一个可以在上次编辑之前根据您的数据模式运行的查询。 除了LIMIT部分

之外,它将在MySql和SQL Server中成功运行
SELECT t1.id, t1.ts, t2.symbol, COALESCE(t4.cnt, 0) cnt
  FROM Table1 t1 JOIN Table2 t2
    ON t1.id = t2.tbl1_id JOIN Table3 t3
    ON t1.tbl3_id = t3.id LEFT JOIN Table4 t4
    ON t1.id = t4.tbl1_id
 WHERE t1.ts BETWEEN '2013-07-25 09:30:00' AND '2013-07-25 16:00:00'
   AND t1.price >= 15.00
 LIMIT 1000 -- LIMIT will work only in MySql

输出:

| ID |                          TS | SYMBOL |  CNT |
----------------------------------------------------
|  2 | July, 25 2013 10:25:00+0000 |    ABC |   19 |
|  3 | July, 25 2013 11:45:00+0000 |    RST |    0 | 
|  4 | July, 25 2013 13:31:00+0000 |    EFG | 2013 |

这是 SQLFiddle (MySql)演示版 这是 SQLFiddle (SQL Server)演示