如果我有一个像
这样的USER表class | age
--------------
1 20
3 56
2 11
1 12
2 20
然后我可以通过
轻松获得每个班级中最年轻的用户select class, min(age)
from user
group by class;
同样,通过用max替换min,我可以得到最老的。但是,我怎样才能在每个班级中获得第10个最年轻(或最老)的 ?顺便说一下,我正在使用MySql v.5.0。
干杯,
答案 0 :(得分:19)
SELECT a.class,
(
SELECT b.age
FROM users b
WHERE b.class = a.class
ORDER BY age
LIMIT 1,1
) as age
FROM users a
GROUP BY a.class
每个班级将获得第二名最年轻的学生。如果您想要第10个最年轻的,那么您需要LIMIT 9,1
,如果您想要第10个最老的,那么您需要ORDER BY age DESC
。
答案 1 :(得分:9)
此处N
显示Nth
条记录oldest
SELECT *
FROM users k
WHERE N = (SELECT
COUNT( DISTINCT age)
FROM users u
WHERE k.age >= u.age
AND k.class = u.class
GROUP BY u.class)
并提供Nth
条记录youngest
SELECT *
FROM users k
WHERE N = (SELECT
COUNT(DISTINCT age)
FROM users u
WHERE k.age <= u.age
AND k.class = u.class
GROUP BY u.class)
答案 2 :(得分:2)
唯一独立于sql的方式(即使你没有子查询mysql&lt; 5)
select u1.class, u1.age, count(*) from user u1 join user u2
on u1.class = u2.class and u1.age >= u2.age
group by u1.class, u1.age
having count(*) = [number]
获得每个班级[数字]最老的
select u1.class, u1.age, count(*) from user u1 join user u2
on u1.class = u2.class and u1.age <= u2.age
group by u1.class, u1.age
having count(*) = [number]
获得每个班级最年轻的[数字]
如果两个人的年龄相同,则可能无法恢复。如果您只想返回其中一个,则需要一个唯一的密钥,查询会更复杂。
答案 3 :(得分:1)
另一种方法是将SQL查询放置在for循环中,每次将新的最小值添加到不断增长的元组中,然后使用WHERE ... NOT IN子句将其过滤掉。我不确定这样做的速度,但是对我来说,它对于非常大的数据集(> 180,000条记录)非常有效。抱歉将SQL和Python混合使用,我是两者的新手。我知道有可能在SQL中执行循环,但我不知道。
idx = tuple()
for i in range(n):
qry = '''SELECT class, min(age)
FROM user
WHERE age NOT IN {}
GROUP BY class'''.format(idx)
cur.execute(qry)
data = cur.fetchall()
d = pd.DataFrame(data)
idx = idx + tuple(d['min(age)'])
答案 4 :(得分:0)
在SQL Server中非常简单:
select * from( select *, row_number() over(order by age asc) as eldest from class order by age asc) a where a.eldest = 10
遵循这种模式,对于MySQL,我想你想看看这个:http://www.xaprb.com/blog/2006/12/02/how-to-number-rows-in-mysql/
答案 5 :(得分:0)
SELECT
userid,
class,
age,
( SELECT COUNT(1) FROM user
WHERE class = c.class AND age > u.age
) AS oldercount
FROM user AS u
WHERE oldercount = 9
GROUP BY class
或
SELECT userid,
class,
age
FROM user AS u
WHERE (SELECT COUNT(1) FROM class WHERE class = c.class AND age > u.age) = 9
GROUP BY class
答案 6 :(得分:0)
任何自己加入表格的答案都会产生一个平方法......
- a JOIN b ON a.class = b.class AND a.age >= b.age
- on average the >= condition will be true for half the class
- 6 people in a class
->6*6/2 = 18
- 10 people in a class
->10*10/2 = 50
-> very rapid growth
随着桌子尺寸的增长,性能会迅速下降。如果你保持小而且不会增长太多,这是一个问题吗?你在那里打电话......
替代方案涉及更多代码,但线性增长......
有很多方法可以完成最后两个步骤。我个人会用......
SELECT
[USER_WITH_IDS].id,
[USER_WITH_IDS].class,
[USER_WITH_IDS].age
FROM
[USER_WITH_IDS]
WHERE
[USER_WITH_IDS].id = (
SELECT
MIN([min].ID) + 8
FROM
[USER_WITH_IDS] AS [min]
WHERE
[min].class = [USER_WITH_IDS].class
)
这给出的是......
获得所需记录的一遍
根据优化器的优劣程度,使用索引(类然后是id)将允许它将最后2次传递合并为1次传递。
2或3次传球,无论桌子或班级规模有多大。线性,而不是平方律...