在不使用 table 联接的情况下计算按 ID 分组的匹配评级?可能吗? MYSQL?

Counting matching ratings grouped by ID without using table joins? Is it possible? MYSQL?

我有一个名为 ratingsPerId 的中间体 table,它是从此处显示的存储过程生成的:

Id   Rating
'1', 'low'
'1', 'low'
'1', 'low'
'1', 'low'
'1', 'low'
'2', 'medium'
'2', 'medium'
'2', 'medium'
'2', 'high'
'2', 'high'
'4', 'high'
'4', 'high'
'4', 'high'
'4', 'high'
'4', 'high'
'9', 'high'
'9', 'high'
'9', 'high'
'9', 'high'
'9', 'high'
'9', 'high'
'9', 'high'
'9', 'high'
'9', 'high'

我想要的是 Id 1,计算所有低点、中点、高点。对以下所有 Id 2、4、9 等执行相同操作...

现在我有一个 table 连接,计算每个 ID 的高点和低点:

drop temporary table if exists t1, t2;
create temporary table t1(ruleid int, high INT);
INSERT into t1(
    SELECT ruleid, count(*) AS High from ratingsPerRuleId  WHERE rating='high' group by ruleid);
create temporary table t2(ruleid int, low int);
INSERT into t2(
    SELECT ruleid, count(*) AS Low from ratingsPerRuleId WHERE rating='low' group by ruleid);

SELECT t1.RuleID, t1.high, t2.low from t1 left join t2 on t1.ruleid=t2.ruleid ;

ID   High  Low
1    NULL   5
2     2    NULL
4     5    NULL
9     9    NULL

如您所见,我需要为 Medium 创建第三个 table 并对其进行连接以获得 Medium 列。

在 MYSQL 中有更简单的方法吗?我觉得有一个简单的语句可以完成这个,我的杂乱 table 小 table 的连接不是必需的,但我对 MYSQL 的了解还不够多,无法获得回答。

我查看了 Count(distinct) 和 Select Distinct,但没有找到答案。

谢谢!

我猜你需要使用 CASE WHEN 表达式。

SELECT 
 Id,
 COUNT(CASE WHEN Rating ='high' THEN 1 END) AS high,
 COUNT(CASE WHEN Rating ='medium' THEN 1 END) AS medium,
 COUNT(CASE WHEN Rating ='low' THEN 1 END) AS low
FROM your_table
GROUP BY Id;

Working Demo

如果您不想使用 CASE WHEN.

,您可以将 SUMMySQL boolean expression 一起使用
SELECT 
 Id,
 SUM(Rating ='high') AS high,
 SUM(Rating ='medium') AS medium,
 SUM(Rating ='low') AS low
FROM your_table
GROUP BY Id;

Working Demo

注: SELECT SUM(a=b) returns 1 only if a=b;

注意: 以下示例输入用于工作演示

| Id | Rating |
|----|--------|
|  1 |    low |
|  1 |    low |
|  1 | medium |
|  1 |   high |
|  2 |   high |

这应该有效(COUNT 不包括空值):

SELECT ruleid
  , COUNT(IF(rating = 'high', 1, NULL)) AS High 
  , COUNT(IF(rating = 'medium', 1, NULL)) AS Medium 
  , COUNT(IF(rating = 'low', 1, NULL)) AS Low 
FROM ratingsPerRuleId 
GROUP BY ruleid
;

此外,如果您愿意,可以将 COUNT(..., NULL)) 替换为 SUM(..., 0))

注意:1000111 的答案更便携,因为旧版本的 MS SQL 不支持 IF(...)