MySQL COUNT 个不同的总数,其中 ALL/EVERY 加入 = 给定值

MySQL COUNT distinct total where ALL/EVERY joined = a given value

我已尝试使用简单的示例数据尽可能地简化这一过程。我有一个名为 Assignments 的 table 和一个名为 Tasks 的 table:

作业

+---------------+------------------+
| ASSIGNMENT_ID |  ASSIGNMENT_NAME |
+---------------+------------------+
|               |                  |
| 1             |  Morning Tasks   |
|               |                  |
| 2             |  Afternoon Tasks |
|               |                  |
| 3             |  Evening Tasks   |
+---------------+------------------+

任务

+---------+----------------+----------------+--------------+
| TASK_ID |  ASSIGNMENT_ID |    TASK_NAME   |  TASK_STATUS |
+---------+----------------+----------------+--------------+
|         |                |                |              |
| 1       |  1             |  Make Bed      |  2           |
|         |                |                |              |
| 2       |  1             |  Brush Teeth   |  2           |
|         |                |                |              |
| 3       |  1             |  Eat Breakfast |  2           |
|         |                |                |              |
| 4       |  1             |  Commute       |  2           |
|         |                |                |              |
| 5       |  2             |  Eat Lunch     |  2           |
|         |                |                |              |
| 5       |  2             |  Wash Dishes   |  1           |
|         |                |                |              |
| 6       |  2             |  Wash Table    |  1           |
|         |                |                |              |
| 7       |  3             |  Make Supper   |  1           |
|         |                |                |              |
| 8       |  3             |  Eat Supper    |  1           |
|         |                |                |              |
| 9       |  3             |  Wash Dishes   |  1           |
+---------+----------------+----------------+--------------+

任务状态中,1表示未完成,2表示完成。

对于每个作业,都有相关的任务。我想计算所有相关任务都已完成的所有分配 (TASK_STATUS = 2)(在我的实际用例中,也满足许多其他条件,但这不在本示例中。 )

所以在这个例子中,答案应该是"1"不是结果列表,只是个数(只是上午任务完成,下午任务已经开始,但不是全部其中一个是完整的。)

我不想知道有多少任务已完成,或者有多少任务已经开始,我只想知道有多少任务已 100% 完成。

我尝试了几种方法,但遇到了心理障碍...

这将给我所有已完成任务的分配

SELECT COUNT(a.assignment_id) AS completed_assignments
FROM assignments AS a
JOIN tasks AS t ON a.assignment_id = t.assignment_id 
WHERE t.task_status = 2
LIMIT 1;

这也会给我所有已完成任务的分配

SELECT COUNT(DISTINCT(CASE WHEN t.task_status = 2 THEN t.assignment_id ELSE NULL END)) AS completed_assignments
FROM assignments AS a
JOIN tasks AS t ON a.assignment_id = t.assignment_id 
WHERE t.task_status = 2
LIMIT 1;

但我想要 ALL 任务完成的地方。 (只统计完成了多少,不列出所有结果。)

这将给出结果数(在结果行中,我可以计算),但我需要查询中的值(以执行其他计算)

SELECT a.assignment_id,
(COUNT(CASE WHEN t.task_status = 2 THEN t.task_id ELSE NULL END)/COUNT(t.task_id)*100) AS percent_complete
FROM assignments AS a
JOIN tasks AS t ON a.assignment_id = t.assignment_id 
GROUP BY a.assignment_id 
HAVING percent_complete = 100;

结果数等于总数

有什么想法吗?

您可以使用 all count = count case when status = 2 来完成。

select * 
from Assignments
where ASSIGNMENT_ID  in (
    select 
        ASSIGNMENT_ID 
    from Tasks
    group by ASSIGNMENT_ID
    having count(1) = count(case when TASK_STATUS = '2' then 1 end)
)

更新:

Appreciate the effort, but I'm looking for a count of completed, not a listing

CREATE TABLE Tasks
  (`TASK_ID` int, `ASSIGNMENT_ID` int, `TASK_NAME` varchar(13), `TASK_STATUS` int)
;

INSERT INTO Tasks
  (`TASK_ID`, `ASSIGNMENT_ID`, `TASK_NAME`, `TASK_STATUS`)
VALUES
  (NULL, NULL, NULL, NULL),
  (1, 1, 'Make Bed', 2),
  (NULL, NULL, NULL, NULL),
  (2, 1, 'Brush Teeth', 2),
  (NULL, NULL, NULL, NULL),
  (3, 1, 'Eat Breakfast', 2),
  (NULL, NULL, NULL, NULL),
  (4, 1, 'Commute', 2),
  (NULL, NULL, NULL, NULL),
  (5, 2, 'Eat Lunch', 2),
  (NULL, NULL, NULL, NULL),
  (5, 2, 'Wash Dishes', 2),
  (NULL, NULL, NULL, NULL),
  (6, 2, 'Wash Table', 2),
  (NULL, NULL, NULL, NULL),
  (7, 3, 'Make Supper', 1),
  (NULL, NULL, NULL, NULL),
  (8, 3, 'Eat Supper', 1),
  (NULL, NULL, NULL, NULL),
  (9, 3, 'Wash Dishes', 1)
;
CREATE TABLE Assignments
  (`ASSIGNMENT_ID` int, `ASSIGNMENT_NAME` varchar(15))
;

INSERT INTO Assignments
  (`ASSIGNMENT_ID`, `ASSIGNMENT_NAME`)
VALUES
  (NULL, NULL),
  (1, 'Morning Tasks'),
  (NULL, NULL),
  (2, 'Afternoon Tasks'),
  (NULL, NULL),
  (3, 'Evening Tasks')
;
select count(1) completedCount
from (
    select 
        ASSIGNMENT_ID 
    from Tasks
    group by ASSIGNMENT_ID
    having count(1) = count(case when TASK_STATUS = '2' then 1 end)
) T
| completedCount |
| -------------: |
|              2 |

db<>fiddle here

如果TasksTASK_STATUS中没有NULL则加入和group by assignment_id并在HAVING子句中设置条件:

select a.assignment_id, a.assignment_name 
from assignments a inner join tasks t
on t.assignment_id = a.assignment_id
group by a.assignment_id, a.assignment_name
having sum(t.task_status = 1) = 0

如果您只需要作业的 ID,则不需要 table Assignments:

select assignment_id
from tasks
group by assignment_id
having sum(task_status = 1) = 0

如果您想要这些作业的计数:

select count(*) from (
  select assignment_id
  from tasks
  group by assignment_id
  having sum(task_status = 1) = 0
) t

参见demo

您可以使用 not exists 条件和相关子查询来过滤,而不是加入和聚合,以确保 task table 中没有状态不是2:

select count(*)
from assignments a
where not exists (
    select 1
    from tasks t
    where 
        t.assignment_id = a.assignment_id
        and t.task_status != 2
)

有了 task(assignment_id, task_status) 上的索引,这应该是一个有效的选择。

如果需要分配列表,可以将count(*)替换为*

Demo on DB Fiddle:

计数:

| count(*) |
| -------: |
|        1 |

详情:

ASSIGNMENT_ID | ASSIGNMENT_NAME
------------: | :--------------
            1 | Morning Tasks  

收到了一些很好的答案(并接受了一个),但无法获得他们的任何方法来为我的其余查询提供正确答案。为了将来参考,这是我最终得到的:

SELECT COUNT(ptc) AS completed_assignments
FROM (SELECT
(COUNT(CASE WHEN task_status = 2 THEN t.task_status ELSE NULL END)/COUNT(t.task_status)) AS ptc
FROM assignments AS a
JOIN tasks AS t ON a.assignment_id = t.assignment_id
WHERE [Other Conditions]
GROUP BY a.assignment_id
HAVING ptc = 1) T

这可能不是最有效的,但在我的情况下我可以用它得到正确的答案...