SQL-запрос для выбора нижней части 2 из каждой категории

В Mysql я хочу выбрать нижнюю часть 2 объекта из каждой категории

Category Value
1        1.3
1        4.8
1        3.7
1        1.6
2        9.5
2        9.9
2        9.2
2        10.3
3        4
3        8
3        16

Предоставление меня:

Category Value
1        1.3
1        1.6
2        9.5
2        9.2
3        4
3        8

Прежде чем я мигрировал от sqlite3, я должен был сначала выбрать самое низкое из каждой категории, затем, исключая что-либо, что соединило, к которому, я должен был снова выбрать самое низкое из каждой категории. Затем что-либо равняется этому новому самый низкий или меньше в выигранной категории. Это также выбрало бы больше чем 2 в случае связи, которая была раздражающей... Это также имело действительно длинное время выполнения.

Моя конечная цель должна считать количество раз, человек находится в одной из самых низких 2 из категории (существует также поле имени), и это - одна первая часть, не знают, как сделать.Спасибо

6
задан Bill Karwin 17 December 2009 в 19:22
поделиться

5 ответов

Вы можете попробовать следующее:

SELECT * FROM (
  SELECT c.*,
        (SELECT COUNT(*)
         FROM user_category c2
         WHERE c2.category = c.category
         AND c2.value < c.value) cnt
  FROM user_category c ) uc
WHERE cnt < 2

Это должно дать вам желаемый результат, но проверьте, в порядке ли производительность.

4
ответ дан 8 December 2019 в 16:03
поделиться

Профсоюз должен работать. Я не уверен в производительности по сравнению с решением Питера.

SELECT smallest.category, MIN(smallest.value)
    FROM categories smallest
GROUP BY smallest.category
UNION
SELECT second_smallest.category, MIN(second_smallest.value)
    FROM categories second_smallest
    WHERE second_smallest.value  > (SELECT MIN(smallest.value) FROM categories smallest WHERE second.category = second_smallest.category)
GROUP BY second_smallest.category
1
ответ дан 8 December 2019 в 16:03
поделиться

Вот решение, которое правильно обрабатывает дубликаты. Имя таблицы - 'zzz', а столбцы - int и float

select
    smallest.category category, min(smallest.value) value
from 
    zzz smallest
group by smallest.category

union

select
    second_smallest.category category, min(second_smallest.value) value
from
    zzz second_smallest
where
    concat(second_smallest.category,'x',second_smallest.value)
    not in ( -- recreate the results from the first half of the union
        select concat(c.category,'x',min(c.value))
        from zzz c
        group by c.category
    )
group by second_smallest.category

order by category

Предостережения:

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

Ваш пробег может отличаться,

- Mark

1
ответ дан 8 December 2019 в 16:03
поделиться
SELECT c1.category, c1.value
FROM catvals c1
LEFT OUTER JOIN catvals c2
  ON (c1.category = c2.category AND c1.value > c2.value)
GROUP BY c1.category, c1.value
HAVING COUNT(*) < 2;

Протестировано на MySQL 5.1.41 с вашими тестовыми данными. Вывод:

+----------+-------+
| category | value |
+----------+-------+
|        1 |  1.30 |
|        1 |  1.60 |
|        2 |  9.20 |
|        2 |  9.50 |
|        3 |  4.00 |
|        3 |  8.00 |
+----------+-------+

(Дополнительные десятичные разряды вызваны тем, что я объявил столбец значение как NUMERIC (9,2) .)

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

8
ответ дан 8 December 2019 в 16:03
поделиться

Вот очень обобщенное решение, которое будет работать для выбора первых n строк для каждой категории. Это будет работать, даже если есть повторяющиеся значения.

/* creating temporary variables */
mysql> set @cnt = 0;
mysql> set @trk = 0;

/* query */
mysql> select Category, Value 
       from (select *, 
                @cnt:=if(@trk = Category, @cnt+1, 0) cnt, 
                @trk:=Category 
                from user_categories 
                order by Category, Value ) c1 
       where c1.cnt < 2;

Вот результат.

+----------+-------+
| Category | Value |
+----------+-------+
|        1 |   1.3 |
|        1 |   1.6 |
|        2 |   9.2 |
|        2 |   9.5 |
|        3 |     4 |
|        3 |     8 |
+----------+-------+

Проверено на MySQL 5.0.88 Обратите внимание, что начальное значение переменной @trk не должно быть наименьшим значением поля Категория.

1
ответ дан 8 December 2019 в 16:03
поделиться
Другие вопросы по тегам:

Похожие вопросы: