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