SQL - 如何聚合和排序父子树?
SQL - How to Aggregate and Sort a Parent Child Tree?
我有以下表格。一项工作可以归入多个类别。一个类别有一个父类别。类别只有两层深。工作仅归入二级类别。我想要一个所有类别的列表,其中包含为每个类别分类的工作数量以及父类别的总数。
下表:
CREATE TABLE jobs (
id INT UNSIGNED AUTO_INCREMENT NOT NULL PRIMARY KEY,
title varchar(255) NOT NULL,
description text NOT NULL
) ENGINE=InnoDB;
CREATE TABLE categories (
id INT UNSIGNED AUTO_INCREMENT NOT NULL PRIMARY KEY,
name varchar(255) NOT NULL,
parent_id INT NOT NULL
) ENGINE=InnoDB;
CREATE TABLE job_categories (
job_id INT UNSIGNED NOT NULL,
category_id INT UNSIGNED NOT NULL,
PRIMARY KEY (`job_id`, `category_id`),
FOREIGN KEY fk_job_id(job_id) REFERENCES jobs(id),
FOREIGN KEY fk_category_id(category_id) REFERENCES categories(id)
) ENGINE=InnoDB;
INSERT INTO categories (id, name, parent_id) VALUES(1, 'Science', 0),(2, 'Biology', 1), (3, 'Chemistry', 1);
INSERT INTO job_categories (job_id, category_id) VALUES(1,2),(1,3), (2,2), (3,2), (4,3);
这是我的 SQL 尝试:
SELECT one.name AS name
, one.name AS sortkey1
, CAST(NULL AS UNSIGNED) AS sortkey2
, COUNT(three.job_id) AS total
FROM categories AS one
INNER JOIN categories AS two ON two.parent_id = one.id
LEFT JOIN job_categories AS three ON three.category_id = two.id
WHERE one.parent_id = 0
GROUP BY name, sortkey1, sortkey2
UNION ALL
SELECT CONCAT(' ',two.name) AS name
, one.name AS sortkey1
, two.name AS sortkey2
, COUNT(three.job_id) AS total
FROM categories AS one
INNER JOIN categories AS two ON two.parent_id = one.id
LEFT JOIN job_categories AS three ON three.category_id = two.id
WHERE one.parent_id = 0
GROUP BY name, sortkey1, sortkey2
ORDER BY sortkey1 , sortkey2
这就是我要实现的目标,例如,如果发布了 4 个职位,其中 3 个职位归类为生物学,4 个职位中的 2 个归类为化学 - 以上 sql 没有给出父类别科学的正确总数。我得到 5 而不是 4:
name sortkey1 sortkey2 total
Science Science 4
Biology Science Biology 3
Chemistry Science Chemistry 2
感谢任何帮助。
SELECT one.name AS name
, one.name AS sortkey1
, CAST(NULL AS UNSIGNED) AS sortkey2
, COUNT(DISTINCT three.job_id) AS total
FROM categories AS one
INNER JOIN categories AS two ON two.parent_id = one.id
LEFT JOIN job_categories AS three ON three.category_id = two.id
WHERE one.parent_id = 0
GROUP BY name, sortkey1, sortkey2
UNION ALL
SELECT CONCAT(' ',two.name) AS name
, one.name AS sortkey1
, two.name AS sortkey2
, COUNT(three.job_id) AS total
FROM categories AS one
INNER JOIN categories AS two ON two.parent_id = one.id
LEFT JOIN job_categories AS three ON three.category_id = two.id
WHERE one.parent_id = 0
GROUP BY name, sortkey1, sortkey2
ORDER BY sortkey1 , sortkey2
我有以下表格。一项工作可以归入多个类别。一个类别有一个父类别。类别只有两层深。工作仅归入二级类别。我想要一个所有类别的列表,其中包含为每个类别分类的工作数量以及父类别的总数。
下表:
CREATE TABLE jobs (
id INT UNSIGNED AUTO_INCREMENT NOT NULL PRIMARY KEY,
title varchar(255) NOT NULL,
description text NOT NULL
) ENGINE=InnoDB;
CREATE TABLE categories (
id INT UNSIGNED AUTO_INCREMENT NOT NULL PRIMARY KEY,
name varchar(255) NOT NULL,
parent_id INT NOT NULL
) ENGINE=InnoDB;
CREATE TABLE job_categories (
job_id INT UNSIGNED NOT NULL,
category_id INT UNSIGNED NOT NULL,
PRIMARY KEY (`job_id`, `category_id`),
FOREIGN KEY fk_job_id(job_id) REFERENCES jobs(id),
FOREIGN KEY fk_category_id(category_id) REFERENCES categories(id)
) ENGINE=InnoDB;
INSERT INTO categories (id, name, parent_id) VALUES(1, 'Science', 0),(2, 'Biology', 1), (3, 'Chemistry', 1);
INSERT INTO job_categories (job_id, category_id) VALUES(1,2),(1,3), (2,2), (3,2), (4,3);
这是我的 SQL 尝试:
SELECT one.name AS name
, one.name AS sortkey1
, CAST(NULL AS UNSIGNED) AS sortkey2
, COUNT(three.job_id) AS total
FROM categories AS one
INNER JOIN categories AS two ON two.parent_id = one.id
LEFT JOIN job_categories AS three ON three.category_id = two.id
WHERE one.parent_id = 0
GROUP BY name, sortkey1, sortkey2
UNION ALL
SELECT CONCAT(' ',two.name) AS name
, one.name AS sortkey1
, two.name AS sortkey2
, COUNT(three.job_id) AS total
FROM categories AS one
INNER JOIN categories AS two ON two.parent_id = one.id
LEFT JOIN job_categories AS three ON three.category_id = two.id
WHERE one.parent_id = 0
GROUP BY name, sortkey1, sortkey2
ORDER BY sortkey1 , sortkey2
这就是我要实现的目标,例如,如果发布了 4 个职位,其中 3 个职位归类为生物学,4 个职位中的 2 个归类为化学 - 以上 sql 没有给出父类别科学的正确总数。我得到 5 而不是 4:
name sortkey1 sortkey2 total
Science Science 4
Biology Science Biology 3
Chemistry Science Chemistry 2
感谢任何帮助。
SELECT one.name AS name
, one.name AS sortkey1
, CAST(NULL AS UNSIGNED) AS sortkey2
, COUNT(DISTINCT three.job_id) AS total
FROM categories AS one
INNER JOIN categories AS two ON two.parent_id = one.id
LEFT JOIN job_categories AS three ON three.category_id = two.id
WHERE one.parent_id = 0
GROUP BY name, sortkey1, sortkey2
UNION ALL
SELECT CONCAT(' ',two.name) AS name
, one.name AS sortkey1
, two.name AS sortkey2
, COUNT(three.job_id) AS total
FROM categories AS one
INNER JOIN categories AS two ON two.parent_id = one.id
LEFT JOIN job_categories AS three ON three.category_id = two.id
WHERE one.parent_id = 0
GROUP BY name, sortkey1, sortkey2
ORDER BY sortkey1 , sortkey2