Select 每个父记录有条件的子记录数
Select number of child record with condition for each parent record
这是我的:
Table: parent
| id | name |
| -- | ---- |
| 1 | foo |
| 2 | bar |
| 3 | baz |
Table: child
| id | parent_id | type_id |
| -- | --------- | ------- |
| 1 | 2 | 2 |
| 2 | 2 | 2 |
| 3 | NULL | 2 |
| 4 | 1 | 1 |
| 5 | NULL | 2 |
| 6 | NULL | 1 |
| 7 | 1 | 2 |
| 8 | 3 | 1 |
我想要select所有父记录,以及每个父记录的类型为 2 的子记录的数量:
| id | name | type_2_count |
| -- | ---- | ------------ |
| 1 | foo | 1 |
| 2 | bar | 2 |
| 3 | baz | 0 |
我试过这个:
SELECT p.id, name, COUNT(c.id) type_2_count
FROM parent p LEFT JOIN child c ON c.parent_id = p.id
WHERE c.type_id = 2
GROUP BY p.id;
| id | name | type_2_count |
| -- | ---- | ------------ |
| 2 | bar | 2 |
| 1 | foo | 1 |
但是它缺少第三条记录。
还有这个:
SELECT p.id, name, t.cnt type_2_count
FROM parent p LEFT JOIN (
SELECT parent_id, COUNT(*) as cnt
FROM child
WHERE type_id = 2
GROUP BY parent_id
) t ON t.parent_id = p.id;
| id | name | type_2_count |
| -- | ---- | ------------ |
| 1 | foo | 1 |
| 2 | bar | 2 |
| 3 | baz | NULL |
但是 type_2_count
是 NULL
而不是第三条记录的 0
。
这是我使用的模式:
CREATE TABLE IF NOT EXISTS parent (
id INT AUTO_INCREMENT,
name VARCHAR(45) NOT NULL,
PRIMARY KEY (id)
) ENGINE=InnoDB;
INSERT INTO parent VALUES (1, 'foo'), (2, 'bar'), (3, 'baz');
CREATE TABLE IF NOT EXISTS child (
id INT AUTO_INCREMENT,
parent_id INT REFERENCES parent(id),
type_id TINYINT NOT NULL,
PRIMARY KEY (id)
) ENGINE=InnoDB;
INSERT INTO child VALUES (1, 2, 2), (2, 2, 2), (3, NULL, 2), (4, 1, 1), (5, NULL, 2), (6, NULL, 1), (7, 1, 2), (8, 3, 1);
在您的第一个查询中,您唯一需要做的更改是将条件从 WHERE
子句移动到 ON
子句:
SELECT p.id, name, COUNT(c.id) type_2_count
FROM parent p LEFT JOIN child c
ON c.parent_id = p.id AND c.type_id = 2
GROUP BY p.id;
并在您的第二个查询中使用 COALESCE()
将 NULL
转换为 0
:
SELECT p.id, name,
COALESCE(t.cnt, 0) type_2_count
FROM parent p LEFT JOIN (
SELECT parent_id, COUNT(*) as cnt
FROM child
WHERE type_id = 2
GROUP BY parent_id
) t ON t.parent_id = p.id;
参见demo。
这是我的:
Table: parent
| id | name |
| -- | ---- |
| 1 | foo |
| 2 | bar |
| 3 | baz |
Table: child
| id | parent_id | type_id |
| -- | --------- | ------- |
| 1 | 2 | 2 |
| 2 | 2 | 2 |
| 3 | NULL | 2 |
| 4 | 1 | 1 |
| 5 | NULL | 2 |
| 6 | NULL | 1 |
| 7 | 1 | 2 |
| 8 | 3 | 1 |
我想要select所有父记录,以及每个父记录的类型为 2 的子记录的数量:
| id | name | type_2_count |
| -- | ---- | ------------ |
| 1 | foo | 1 |
| 2 | bar | 2 |
| 3 | baz | 0 |
我试过这个:
SELECT p.id, name, COUNT(c.id) type_2_count
FROM parent p LEFT JOIN child c ON c.parent_id = p.id
WHERE c.type_id = 2
GROUP BY p.id;
| id | name | type_2_count |
| -- | ---- | ------------ |
| 2 | bar | 2 |
| 1 | foo | 1 |
但是它缺少第三条记录。
还有这个:
SELECT p.id, name, t.cnt type_2_count
FROM parent p LEFT JOIN (
SELECT parent_id, COUNT(*) as cnt
FROM child
WHERE type_id = 2
GROUP BY parent_id
) t ON t.parent_id = p.id;
| id | name | type_2_count |
| -- | ---- | ------------ |
| 1 | foo | 1 |
| 2 | bar | 2 |
| 3 | baz | NULL |
但是 type_2_count
是 NULL
而不是第三条记录的 0
。
这是我使用的模式:
CREATE TABLE IF NOT EXISTS parent (
id INT AUTO_INCREMENT,
name VARCHAR(45) NOT NULL,
PRIMARY KEY (id)
) ENGINE=InnoDB;
INSERT INTO parent VALUES (1, 'foo'), (2, 'bar'), (3, 'baz');
CREATE TABLE IF NOT EXISTS child (
id INT AUTO_INCREMENT,
parent_id INT REFERENCES parent(id),
type_id TINYINT NOT NULL,
PRIMARY KEY (id)
) ENGINE=InnoDB;
INSERT INTO child VALUES (1, 2, 2), (2, 2, 2), (3, NULL, 2), (4, 1, 1), (5, NULL, 2), (6, NULL, 1), (7, 1, 2), (8, 3, 1);
在您的第一个查询中,您唯一需要做的更改是将条件从 WHERE
子句移动到 ON
子句:
SELECT p.id, name, COUNT(c.id) type_2_count
FROM parent p LEFT JOIN child c
ON c.parent_id = p.id AND c.type_id = 2
GROUP BY p.id;
并在您的第二个查询中使用 COALESCE()
将 NULL
转换为 0
:
SELECT p.id, name,
COALESCE(t.cnt, 0) type_2_count
FROM parent p LEFT JOIN (
SELECT parent_id, COUNT(*) as cnt
FROM child
WHERE type_id = 2
GROUP BY parent_id
) t ON t.parent_id = p.id;
参见demo。