Подтвердить что ты не робот

SQL выбирает n-й член группы

Если у меня есть таблица USER, например

class | age
--------------
1       20    
3       56
2       11
1       12
2       20

Затем я могу легко получить младшего пользователя в каждом классе через

select class, min(age)
from   user
group by class;

Аналогично, заменив min max, я могу получить самый старый. Но как я могу получить 10-ю младшую (или самую старую) в каждом классе? Кстати, я использую MySql v.5.0.

Приветствия,

4b9b3361

Ответ 1

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.

Ответ 2

Здесь 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)

Ответ 3

Единственный независимый 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]

получает вас [число] младший в классе

Если два человека имеют одинаковый возраст, он может не работать, поскольку оба возвращаются. Если вы хотите только вернуть один из них, вам понадобится уникальный ключ, и запрос будет более сложным.

Ответ 4

В 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

SELECT      идентификатор пользователя,
     класс,
     возраст,
     (SELECT COUNT (1) FROM пользователя
          WHERE class= c.class AND age > u.age
     ) AS oldercount
ОТ пользователя AS u
WHERE oldercount = 9 Класс GROUP BY

или

SELECT userid,
         класс,
         возраст
  ОТ пользователя AS u
  WHERE (SELECT COUNT (1) FROM class WHERE class= c.class AND age > u.age) = 9
Класс GROUP BY

Ответ 6

Любой ответ, который присоединяется к таблице на нем, будет создавать квадратный закон...

- 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, упорядоченным по классу, а затем Age
  • Теперь для каждого класса найдите MIN (id)
  • Теперь для каждого класса rinf запись, где is = MIN (id) + 8 (для 9-го старшего)

Существует много способов сделать последние 2 шага. Я лично использовал бы...

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
                         )

Что это дает...

  • Один проход для создания новых идентификаторов
  • Один проход, чтобы получить MIN (id) для каждого класса
  • Один проход для получения требуемых записей

  • И в зависимости от того, насколько хорош оптимизатор, используя индекс (class then id), он сможет объединить последние 2 прохода в 1 проход.

2 или 3 прохода, независимо от того, насколько большой размер таблицы или класса. Линейный, а не квадратный закон...