SQL选择组的第n个成员

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了SQL选择组的第n个成员相关的知识,希望对你有一定的参考价值。

如果我有一个像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。

干杯,

答案
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

另一答案

在这里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)
另一答案

唯一的sql独立方式(即使你没有子查询mysql <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]

得到你每班最年轻的[数字]

如果两个人的年龄相同,则可能无法正常工作。如果您只想返回其中一个,则需要一个唯一的密钥,查询会更复杂。

另一答案

在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/

另一答案

任何自己加入表格的答案都会产生一个平方律......

- 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

随着工作台尺寸的增大,性能将迅速下降。如果你保持小而且不会增长太多,这是一个问题吗?你在那里打电话......

另一种选择涉及更多代码,但线性增长......

  • 首先,将所有记录插入到新表中,其中包含IDENTITY字段,按Class排序,然后按Age排序
  • 现在,对于每个类,找到MIN(id)
  • 现在,对于每个班级,请记录以下内容:= MIN(id)+ 8(对于第9个老人)

最后两步有很多种方法。我个人会用......

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
  • 一次获取每个类的MIN(id)
  • 获得所需记录的一遍
  • 并且根据优化器的好坏,使用索引(类然后是id)将允许它将最后2个传递组合成1个传递。

无论表格或班级规模有多大,都可以获得2或3次通行证。线性,而不是平方律......

另一答案
 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

以上是关于SQL选择组的第n个成员的主要内容,如果未能解决你的问题,请参考以下文章

获取第n个连续组的第一行/最后一行

如何在 SQL 查询中选择每个组的第一行?

在sql中选择每个组的第一行[重复]

如何根据条件选择每个组的 x 或 y 成员

有重复组时选择最后一组的第一条记录

获取每组的前 n 个结果 [重复]