SQL - дайте мне 3 хита только для каждого типа - PullRequest
8 голосов
/ 23 января 2011

У меня какая-то невыполнимая просьба :).

У меня есть таблица, в которой один из столбцов называется type.Я хотел бы выбрать 3 записи для каждого типа в этом столбце.Возможно ли это?

Обратите внимание, что я использую MySQL и Sphinx.

ОБНОВЛЕНИЕ: Структура таблицы

id       title        type
1        AAAA         string1
2        CCCC         string2
3        EEEE         string2
4        DDDD         string2
5        FFFF         string2
6        BBBB         string2
6        BBBB         string2

То, что я хочу, чтобы мой MySQL возвращал (вверхдо 3 записей для каждого типа, упорядоченного по названию):

id       title        type
1        AAAA         string1
6        BBBB         string2
2        CCCC         string2
4        DDDD         string2

Ответы [ 4 ]

12 голосов
/ 23 января 2011
select id, title, type
from   (select id, title, type,
               @num := if(@group = type, @num + 1, 1) as row_number,
               @group := type as dummy
        from   your_table
        order by type, title) as x
where  row_number <= 3

(использует другую статью на том же сайте, что и ответ Мартина Викмана !)

2 голосов
/ 24 января 2011

Если у вас есть индекс на (type, title), и вы знаете возможные значения для type, я считаю, что динамический SQL - это путь (на этот раз) для лучшей производительности.

Для каждого возможного значения type добавьте объединение всех и выбор для этого конкретного типа.Окончательный запрос будет выглядеть следующим образом:

(select * from t1 where type = 'string1' order by title limit 3)
  union all
(select * from t1 where type = 'string2' order by title limit 3)
  union all
(select * from t1 where type = 'string3' order by title limit 3);

Он выполняется менее чем за 1 секунду для таблицы с 1 000 000 строк, тогда как для других решений (Martins & Cyberkiwis) требуется примерно 11 секунд.

Разница в том, что вышеприведенный объединенный запрос может извлечь первые три записи заголовка для каждого типа, а затем stop , тогда как функция имитированной аналитики должна сканировать всю таблицу.

2 голосов
/ 23 января 2011

Когда таблица большая и сбор более непредсказуемый, нумерация строк должна быть упорядочена по типу во внутреннем запросе, чтобы побочные эффекты работали.

select id, title, type
from (select id, title, type,
        @r := CASE WHEN @g = type THEN @r+1 ELSE 1 END r,
        @g := type
      from tbl
      order by type, title) as x
where row_number <= 3
# order by type, title

Другой способ сделать это без использования побочных эффектов, если нет двух одинаковых записей (title, type, id), приведен ниже. При этом используется только стандартный ANSI SQL92 SQL. Это может быть медленнее, чем выше.

select A.id, A.title, A.type
from tbl A
left join tbl B on
   A.title = B.title and
   (A.type < B.type or
   (A.type = B.type and A.id < A.id))
group by A.id, A.title, A.type
having count(B.title) <= 2
0 голосов
/ 23 января 2011

Оформить эту статью. Дано:

+--------+------------+-------+
| type   | variety    | price |
+--------+------------+-------+
| apple  | gala       |  2.79 | 
| apple  | fuji       |  0.24 | 
| apple  | limbertwig |  2.87 | 
| orange | valencia   |  3.59 | 
| orange | navel      |  9.36 | 
| pear   | bradford   |  6.05 | 
| pear   | bartlett   |  2.14 | 
| cherry | bing       |  2.55 | 
| cherry | chelan     |  6.33 | 
+--------+------------+-------+

Запрос:

select type, variety, price
from fruits
where (
   select count(*) from fruits as f
   where f.type = fruits.type and f.price < fruits.price
) <= 2;
...