Mysql 为什么这个左连接会消除另一个表中没有记录的记录?

Mysql 为什么这个左连接会消除另一个表中没有记录的记录?,mysql,sql,join,left-join,Mysql,Sql,Join,Left Join,我有一个MySQL左连接问题 我有三张桌子要加入 人员表: CREATE TABLE person ( id INT NOT NULL AUTO_INCREMENT, type ENUM('student', 'staff', 'guardian') NOT NULL, first_name CHAR(30) NOT NULL, last_name CHAR(30) NOT NULL, gender ENUM('m', 'f') NOT NULL,

我有一个MySQL左连接问题

我有三张桌子要加入

人员表:

CREATE TABLE person ( id INT NOT NULL AUTO_INCREMENT, type ENUM('student', 'staff', 'guardian') NOT NULL, first_name CHAR(30) NOT NULL, last_name CHAR(30) NOT NULL, gender ENUM('m', 'f') NOT NULL, dob VARCHAR(30) NOT NULL, PRIMARY KEY (id) ); 创建表格人员( id INT非空自动增量, 类型ENUM('student'、'staff'、'guardian')不为空, 名字字符(30)不为空, 姓氏字符(30)不为空, 性别枚举('m','f')不为空, dob VARCHAR(30)不为空, 主键(id) ); 学生桌:

CREATE TABLE student ( id INT NOT NULL AUTO_INCREMENT, person_id INT NOT NULL, primary_guardian INT NOT NULL, secondary_guardian INT, join_date VARCHAR(30) NOT NULL, status ENUM('current', 'graduated', 'expelled', 'other') NOT NULL, tutor_group VARCHAR(30) NOT NULL, year_group VARCHAR(30) NOT NULL, PRIMARY KEY (id), FOREIGN KEY (person_id) REFERENCES person(id) ON DELETE CASCADE, FOREIGN KEY (primary_guardian) REFERENCES guardian(id), FOREIGN KEY (secondary_guardian) REFERENCES guardian(id), FOREIGN KEY (tutor_group) REFERENCES tutor_group(name), FOREIGN KEY (year_group) REFERENCES year_group(name) ); CREATE TABLE incident ( id INT NOT NULL AUTO_INCREMENT, student INT NOT NULL, staff INT NOT NULL, guardian INT NOT NULL, sent_home BOOLEAN NOT NULL, illness_type VARCHAR(255) NOT NULL, action_taken VARCHAR(255) NOT NULL, incident_date DATETIME NOT NULL, PRIMARY KEY (id), FOREIGN KEY (student) REFERENCES student(id), FOREIGN KEY (staff) REFERENCES staff(id), FOREIGN KEY (guardian) REFERENCES guardian(id) ); 创建表学生( id INT非空自动增量, person_id INT不为空, primary_guardian INT不为空, 中学(国际), join_date VARCHAR(30)不为空, 状态枚举(“当前”、“已毕业”、“已驱逐”、“其他”)不为空, tutor_组VARCHAR(30)不为空, 年份组VARCHAR(30)不为空, 主键(id), 外键(person_id)在删除级联上引用person(id), 外键(主监护人)引用监护人(id), 外键(辅助监护人)引用监护人(id), 外键(导师组)引用导师组(名称), 外键(年份组)引用年份组(名称) ); 和事件表:

CREATE TABLE student ( id INT NOT NULL AUTO_INCREMENT, person_id INT NOT NULL, primary_guardian INT NOT NULL, secondary_guardian INT, join_date VARCHAR(30) NOT NULL, status ENUM('current', 'graduated', 'expelled', 'other') NOT NULL, tutor_group VARCHAR(30) NOT NULL, year_group VARCHAR(30) NOT NULL, PRIMARY KEY (id), FOREIGN KEY (person_id) REFERENCES person(id) ON DELETE CASCADE, FOREIGN KEY (primary_guardian) REFERENCES guardian(id), FOREIGN KEY (secondary_guardian) REFERENCES guardian(id), FOREIGN KEY (tutor_group) REFERENCES tutor_group(name), FOREIGN KEY (year_group) REFERENCES year_group(name) ); CREATE TABLE incident ( id INT NOT NULL AUTO_INCREMENT, student INT NOT NULL, staff INT NOT NULL, guardian INT NOT NULL, sent_home BOOLEAN NOT NULL, illness_type VARCHAR(255) NOT NULL, action_taken VARCHAR(255) NOT NULL, incident_date DATETIME NOT NULL, PRIMARY KEY (id), FOREIGN KEY (student) REFERENCES student(id), FOREIGN KEY (staff) REFERENCES staff(id), FOREIGN KEY (guardian) REFERENCES guardian(id) ); 创建表事件( id INT非空自动增量, 学生整数不为空, staff INT不为空, guardian INT不为空, 已发送\u回家布尔值不为空, 类型VARCHAR(255)不为空, 采取的措施\u VARCHAR(255)不为空, 事件日期日期时间不为空, 主键(id), 外键(学生)参考学生(id), 外键(员工)参考员工(id), 外键(监护人)引用监护人(id) ); 我试图选择的是每个学生在9年级的名字、姓氏和事件数

以下是我对查询的最佳尝试:

SELECT p.first_name, p.last_name, COUNT(i.student) FROM person p, student s LEFT JOIN incident i ON s.id = i.student WHERE p.id = s.person_id AND s.year_group LIKE "%Year 9%"; 选择p.first\u name、p.last\u name、COUNT(i.student) 从人员p开始,学生s在s.id=i.student上左加入事件i 其中p.id=s.person_id和s.year_组,如“%year 9%”; 但是,它会忽略任何没有事件的学生,这不是我想要的-他们应该显示,但计数为0。如果我去掉左连接和计数,那么我得到了我所期望的所有学生

我可能误解了left join,但我认为它应该做什么,本质上就是我想做的

谢谢你的帮助


亚当

那不是你要找的一个左外联吗?我的术语可能弄错了?这不是第一次了。但阿隆的答案是可行的

或者,您可以使用以下方法避免
左连接


你所做的很好,你只是错过了分组条款

SELECT p.first_name, p.last_name, COUNT(i.student)
FROM person p, student s  LEFT JOIN incident i ON s.id = i.student 
WHERE p.id = s.person_id AND s.year_group LIKE "%Year 9%"
GROUP BY p.first_name, p.last_name;
这里有一些测试数据

insert into person values(1, 'student', 'Alice', 'Foo', 'f','1970-01-01');
insert into person values(2, 'student', 'Bob', 'Bar', 'm','1970-01-01');

insert into student values(1,1,0,0,'', 'current','','Year 9');
insert into student values(2,2,0,0,'', 'current','','Year 9');

insert into incident values(1,1,0,0,0,'flu','chicken soup', '2008-01-08');
下面是添加了group by的查询输出:

+------------+-----------+------------------+
| first_name | last_name | COUNT(i.student) |
+------------+-----------+------------------+
| Alice      | Foo       |                1 |
| Bob        | Bar       |                0 |
+------------+-----------+------------------+
您可以通过从where子句生成join子句并根据person id进行分组来进一步清理查询:

SELECT p.first_name, p.last_name, COUNT(i.student)
FROM person p
INNER JOIN student s ON(p.id = s.person_id)
LEFT JOIN incident i ON(s.id = i.student)
WHERE s.year_group LIKE "%Year 9%"
GROUP BY p.id;

您首先使用了countwithgroupby,并混合了连接的“where”和“on”语法。 试试这个:

SELECT p.first_name, p.last_name, COUNT(i.student)
FROM person p
JOIN student s on p.id = s.person
LEFT JOIN incident i ON s.id = i.student 
WHERE s.year_group LIKE "%Year 9%"
GROUP BY P.id;

如果我没记错的话,左连接就是左外连接。(与“加入”或“内部加入”形成对比。)感谢Paul的课:)在重新阅读我的答案后,你完全正确:)这是迄今为止对这个问题的最佳答案,所以你对这个问题投了更高的票。好的,这很有效,非常感谢。快速提问,也许没关系,我下次会记得,但为什么它需要GROUP BY?count()是一个聚合函数,这意味着它要么需要对结果集中的所有行进行操作,要么需要被告知如何将行分组在一起。如果将常规列与聚合函数混合使用,则需要GROUPBY子句。