我正在编写一个查询,该查询按(height, sex)
对用户表进行分组,然后以height
和sex
的组合获得具有最小权重的用户名。
如果您想跳到实际的查询,这里是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是因为它是第一行,但是为什么要这么做呢?真是奇怪又出乎意料。
答案 0 :(得分:1)
您没有正确使用GROUP BY
。在大多数RDBMS中,通常的规则是所有未聚合的列都必须出现在GROUP BY
子句中。只有较早版本的MySQL才允许违反该规则(在较新的版本中,您需要禁用选项ONLY_FULL_GROUP_BY
),但这会导致不可预测的结果,如您在此处所遇到的。
要展示共享相同的weight
和height
的推子组中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
)
合理比例:NOT EXITS
条件与子查询结合使用,可以消除存在相同height
和sex
但具有较小weight
的另一个记录的记录,并保留在结果集仅对每个weight
元组具有最小height/sex
的记录。我们使用SELECT 1
是因为我们不需要子查询来返回实际结果,我们只想知道它是否返回 something 。
答案 1 :(得分: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
组合的最小值的用户。
答案 2 :(得分: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使所有组的性别和身高最小化,其余是简单的内部联接,其中仅选择相关名称