使用 Count + STRING_AGG,显示不同的值

Using Count + STRING_AGG, to display distinct values

我正在尝试将 COUNTSTRING_AGG 一起使用。问题是,在子查询中,它根据需要进行计数,当有 1 名员工参加课程时,我的计数为 1,但是当我 运行 完整查询时,我得到的结果翻了一番,如下所示:

COMPLETED: 1, COMPLETED: 1

当我将 DISTINCT 计入 STRING_AGG 时,它给我一个错误。知道如何实现吗?

SELECT s1.course_id
      , s1.course_name
      , STRING_AGG(CONCAT(ts.training_status_name 
          + ': ' + 
          CAST(countt as varchar), ''),', ') AS num_of_attendies_and_status
FROM  (
         SELECT th.course_id
                , c.course_name
                , COUNT(DISTINCT e.employee_id) AS countt
         FROM course as c
                INNER JOIN training_history th ON c.course_id = th.course_id
                INNER JOIN employee e ON th.employee_id = e.employee_id
         GROUP BY th.course_id, course_name
      ) s1
      INNER JOIN training_history th ON s1.course_id = th.course_id
      INNER JOIN training_status ts ON th.training_status_id = ts.training_status_id
      INNER JOIN employee e ON th.employee_id = e.employee_id
GROUP BY s1.course_id
      , s1.course_name

输出示例:

Course_id Course_name num_of_attendies_and_status
5 React COMPLETED: 1, COMPLETED: 1
7 C# COMPLETED: 1, COMPLETED: 1
9 Selenium REGISTERED: 1, REGISTERED: 1
13 Finance IN PROGRESS: 1, IN PROGRESS: 1

我有 table 名员工,员工姓名为 employee_id,课程 ID 为 training_history,这是 course_id 和 employee_id 之间的链接,和培训状态,根据课程 ID 显示课程状态名称。我这里有 3 个状态:完成、注册、进行中。

问题是,当我 运行 子查询时:

  SELECT th.course_id
        , c.course_name
        , COUNT(DISTINCT e.employee_id) AS countt
  FROM   course as c
             INNER JOIN training_history th ON c.course_id = th.course_id
             INNER JOIN employee e ON th.employee_id = e.employee_id
  GROUP BY th.course_id
        , course_name

我得到以下输出:

Course_id Course_name num_of_attendies_and_status
5 React 1
7 C# 1
9 Selenium 1
13 Finance 1

但是第一个查询的最后一个,翻了一番。问题是有 2 名重复的相同员工。所以我需要以某种方式区分它们。在子查询中 COUNT(DISCTINCT employee_id) 工作正常。但是在主查询中,它翻了一番。对于难以理解的问题,我深表歉意。希望有什么是清楚的。

我用 CTE 收集了 count(distinct) 的信息。 注意,我在您的示例数据中添加了一些行,使每门课程有 2 个状态。

with training as
(SELECT 
  c.course_id,
  c.course_name,
  th.training_status_id as t_status_id,
  count(distinct employee_id) as count_emp
from dbo.course c
join dbo.training_history th on c.course_id = th.course_id
group by 
  c.course_id,
  c.course_name,
  th.training_status_id)
select 
  t.course_id,
  t.course_name,
  string_agg(concat(ts.training_status_name,':',count_emp),',') as num_of_attendies_and_status
from training t
join dbo.training_status ts
on t.t_status_id = ts.training_status_id
group by 
  t.course_id,
  t.course_name
;
course_id | course_name                                                  | num_of_attendies_and_status   
--------: | :----------------------------------------------------------- | :-----------------------------
        5 | React - The Complete Guide (incl Hooks, React Router, Redux) | COMPLETED: 1, COMPLETED: 1    
        7 | Learn Parallel Programming with C# and .NET                  | COMPLETED: 1, COMPLETED: 1    
        9 | Selenium WebDriver with Docker, Jenkins & AWS                | REGISTERED: 1, REGISTERED: 1  
       13 | Finance for Non Finance Executives                           | IN PROGRESS: 1, IN PROGRESS: 1

*db<>fiddle here5dab7f3db67ba78a)