代码之家  ›  专栏  ›  技术社区  ›  Keith Lawrence

MySQL左连接选择不选择所有左侧记录?

  •  1
  • Keith Lawrence  · 技术社区  · 16 年前

    我得到了一个奇怪的结果 MySQL SELECT 涉及的查询 LEFT JOIN 我不明白我对 左连接 是错误的,还是我看到了一个真正奇怪的行为。

    我有一个两张表,有多对一的关系:对于 table 1 中有0个或多个记录 table 2 . 我想选择表1中的所有记录,其中一列统计表2中相关记录的数量。据我所知, 左连接 应始终返回 LEFT 陈述的一方。

    下面是一个测试数据库,展示了问题:

    CREATE DATABASE Test;
    USE Test;
    
    CREATE TABLE Dates (
       dateID INT UNSIGNED NOT NULL AUTO_INCREMENT,
       date DATE NOT NULL,
       UNIQUE KEY (dateID)
    ) TYPE=MyISAM;
    
    
    CREATE TABLE Slots (
       slotID INT UNSIGNED NOT NULL AUTO_INCREMENT,
       dateID INT UNSIGNED NOT NULL,
       UNIQUE KEY (slotID)
    ) TYPE=MyISAM;
    
    INSERT INTO Dates (date) VALUES ('2008-10-12'),('2008-10-13'),('2008-10-14');
    INSERT INTO Slots (dateID) VALUES (3);
    

    日期表有三条记录,槽1-和那个记录指向日期中的第三条记录。

    如果我执行以下查询…

    SELECT d.date, count(s.slotID) FROM Dates AS d LEFT JOIN Slots AS s ON s.dateID=d.dateID GROUP BY s.dateID;
    

    …我希望看到一张表,其中三行在-2行,计数为0,一行计数为1。但我实际看到的是:

    +------------+-----------------+
    | date       | count(s.slotID) |
    +------------+-----------------+
    | 2008-10-12 |               0 |
    | 2008-10-14 |               1 |
    +------------+-----------------+
    

    出现第一个零计数记录,但忽略后一个零计数记录。

    我是做了什么错事,还是只是不明白左边的join应该做什么?

    6 回复  |  直到 9 年前
        1
  •  6
  •   Cade Roux    16 年前

    你需要 GROUP BY d.dateID . 在你的两个案例中, s.DateID NULL ( LEFT JOIN )它们结合在一起。

    我认为您还会发现这是无效的(ansi)sql,因为d.date不是 GROUP BY 或聚合操作的结果,并且不应 SELECT 预计起飞时间。

        2
  •  2
  •   thoroughly    16 年前

    我想你的意思是按D.dateid分组。

        3
  •  1
  •   leif    16 年前

    尝试按s.dateid删除组

        4
  •  1
  •   J.J.    16 年前

    10-12和10-13的日期ID由您分组在一起。因为它们是2个空值,所以计数被计算为0。

        5
  •  1
  •   John Nilsson    16 年前

    我不知道这在MySQL中是否有效,但是将来您可能会使用以下语法来避免这个错误

    SELECT date, count(slotID) as slotCount
    FROM Dates LEFT OUTER JOIN Slots USING (dateID)
    GROUP BY (date)
    

    通过使用using子句,您不需要跟踪两个dateid。

        6
  •  0
  •   Veynom    16 年前

    用d.dateid替换group by s.dateid。