MySQL GroupBy在多列上的怪异行为

问题描述 投票:0回答:3

[我正在编写一个查询,该查询将用户表按(height, sex)分组,然后以heightsex的组合获得具有最小权重的用户名。

如果您想跳到实际的查询,这里是SQLFiddle,带有一个最小的代表性示例。

如果您不想打开该URL,这就是我在说的。给定一个表,例如:

| height | sex    | name    | weight |
|-------:|--------|---------|--------|
| 100    | female | Alice   | 150    |
| 100    | female | Barbara | 130    |
| 100    | female | Candice | 100    |

以及执行此操作的查询,如下所示:

SELECT name, min(weight) from users
group by height, sex

为什么查询输出:

|  name | min(weight) |
|------:|-------------|
| Alice | 100         |

我真正想要的是Candice, 100而不是Alice, 100

我发现它选择Alice是因为它是第一行,但是为什么要这样做呢?这真的很奇怪和出乎意料。

mysql sql group-by greatest-n-per-group
3个回答
1
投票

我将使用相关的子查询,但不能使用花哨的逻辑:

select u.*
from users u
where u.weight = (select min(u2.weight)
                  from users u2
                  where u2.height = u.height and u2.sex = u.sex
                 );

即,返回权重为height / sex组合的最小值的用户。


1
投票

您没有正确使用GROUP BY。在大多数RDBMS中,通常的规则是所有未聚合的列都必须出现在GROUP BY子句中。仅MySQL的较早版本允许违反该规则(在较新版本中,您需要禁用选项ONLY_FULL_GROUP_BY),但这可能会导致不可预测的结果,如您在此处所遇到的。

[要显示共享相同weightheight的recred组中具有最小sex的用户,一种解决方案是将NOT EXISTS条件与相关子查询一起使用,例如:

SELECT *
FROM users u
WHERE NOT EXISTS (
    SELECT 1
    FROM users u1
    WHERE 
        u1.height = u.height 
        AND u1.sex = u.sex
        AND u1.weight < u.weight
)

Rationale:NOT EXITS条件与子查询结合使用会消除那些存在另一个具有相同heightsex但具有较小weight记录的记录,仅在结果集中保留具有最小记录的记录每个weight元组的height/sex。我们使用SELECT 1是因为我们不需要子查询来返回实际结果,我们只想知道它是否返回something


0
投票

具有这些数据

CREATE TABLE users
(`height` varchar(8), `sex` varchar(8), `name` varchar(9), `weight` varchar(8))
;

INSERT INTO users
(`height`, `sex`, `name`, `weight`)
VALUES
('100', 'female', 'Alice', '150'),
('100', 'female', 'Barbara', '130'),
('100', 'female', 'Candice', '100'),
('190', 'male', 'John', '185'),
('190', 'male', 'Bert', '130'),
('190', 'male', 'John', '113')
;

和此sql语句

Select name, u.weight
from users u inner join 
(Select min(weight) weight ,sex,height
From users
Group by height, sex ) u1 
On u.sex= u1.sex and u.height = u1.height
and u.weight = u1.weight
GROUP By u.height,u.sex;

您得到以下结果

name        weight
Candice     100
John        113

第二个选择语句u1使您所有性别和身高的最小体重,其余是简单的内部联接,其中仅选择了相关名称

© www.soinside.com 2019 - 2024. All rights reserved.