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
如果Tasks
的TASK_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(*)
替换为*
。
计数:
| 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
这可能不是最有效的,但在我的情况下我可以用它得到正确的答案...
我已尝试使用简单的示例数据尽可能地简化这一过程。我有一个名为 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
如果Tasks
的TASK_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(*)
替换为*
。
计数:
| 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
这可能不是最有效的,但在我的情况下我可以用它得到正确的答案...