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

у меня есть таблица 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.

Ура,

Ответы на вопрос(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, упорядоченным по классу, а затем по возрасту.Теперь для каждого класса найдите МИН (id)Теперь для каждого класса промыть запись где = 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
                         )

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

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

Один проход, чтобы получить нужные вам записи

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

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

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

 David Raznick20 янв. 2009 г., 22:46
Метод в ссылке работает, но это немного взломать. Это тоже очень быстро. Для одного хорошо, для производства нет!
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

вы бы сделалиLIMIT 9,1 и если бы вы хотели 10-й самый старый, вы бы сделалиORDER BY age DESC.

 Marcus11 дек. 2013 г., 01:17
Похоже, что это не работает для MySQL v5.5: ОШИБКА 1235 (42000): эта версия MySQL еще не поддерживает 'LIMIT & IN / ALL / ANY / SOME subquery'
 Paolo Bergantino20 янв. 2009 г., 22:16
Ой, не заметил, что он хотел сгруппировать. Крепление ...
 Dónal20 янв. 2009 г., 22:13
Это даст мне 10-й самый старший в целом, а не 10-й самый старый в каждом классе.

Вот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)
 mzalazar31 мар. 2015 г., 12:35
Вы спасли мой день, спасибо !!!!!!
 Mr.P17 июн. 2016 г., 07:46
классно !! это должно быть помечено как ответ
 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
 David Raznick20 янв. 2009 г., 22:49
Также понадобится уникальный ключ, если два человека были одного возраста, и вы хотели вернуть только один из них.
 MatBailie21 янв. 2009 г., 02:56
Оба повторно сканируют весь класс для каждой записи в исходной таблице. Должно быть выполнимо, не нарушая квадратный закон ...
 Dónal20 янв. 2009 г., 23:25
Первый запрос вызывает ошибку: «Неизвестный столбец« младше »в« предложении где »»

Ваш ответ на вопрос