Как выбрать все записи, где поле имеет определенное значение, пока не появится запись с другим значением? - PullRequest
1 голос
/ 01 февраля 2012

Допустим, у нас есть таблица с COLUMN1 и COLUMN 2. Вот пример записей:

COLUMN 1 | COLUMN 2
124 | 12
124 | 11
124 | 10
124 | 9
26  | 8
65  | 7
65  | 6
65  | 5
65  | 4
23  | 3
124 | 2
124 | 1
124 | 0

В этом нет абсолютно никакой закономерности, но я бы хотел получить:

COUNT(*) | COLUMN 1 | Smallest Column 2
4 | 124 | 9
1 | 26  | 8
4 | 65  | 4
1 | 23  | 3
3 | 124 | 0

До сих пор я делал это с PHP, но я хотел бы найти способ сделать это в MySQL, так как я уверен, что это будет намного эффективнее. Проблема в том, что я даже не могу придумать, с чего начать. Обычная GROUP BY COLUMN 1 не будет работать, потому что я хочу получить два результата для 124, поскольку она появляется в двух разных случаях. Я часами возился и изучал документацию и Google, но пока ничего не смог найти, и мне было интересно, сможет ли кто-нибудь из вас указать мне правильное направление. Это возможно даже с MySQL?

Ответы [ 2 ]

2 голосов
/ 01 февраля 2012

Ну, это заняло немного возни, но вот оно!

Предполагается, что в вашей таблице есть столбец id, который вы заказываете для получения согласованного порядка (если у вас нет столбца id, порядка по метке времени или чего-либо еще во внутреннем запросе).

set @prev := '', @low := 0, @cnt := 0, @grp :=0;
select cnt, column1, low
from (
    select
        column2, 
        @low := if(@prev = column1, least(column2, @low), column2) low,
        @cnt := if(@prev = column1, @cnt + 1, 1) cnt,
        @grp := if(@prev = column1, @grp, @grp + 1) grp,
        @prev := column1 column1
    from (select column1, column2 from so9091342 order by id) x
    order by grp, cnt desc) y
group by grp;

Вот sql, необходимый для настройки таблицы для тестирования:

create table so9091342 (id int primary key auto_increment, column1 int, column2 int);
insert into so9091342 (column1, column2) values (124,12),(124,11),(124,10),(124,9),(26,8),(65,7),(65,6),(65,5),(65,4),(23,3),(124,2),(124,1),(124,0);

Вывод вышеуказанного запроса:

+------+---------+------+
| cnt  | column1 | low  |
+------+---------+------+
|    4 |     124 |    9 |
|    1 |      26 |    8 |
|    4 |      65 |    4 |
|    1 |      23 |    3 |
|    3 |     124 |    0 |
+------+---------+------+

p.s. Я назвал таблицу so9091342, потому что это так ID вопроса # 9091342.

1 голос
/ 01 февраля 2012

Интересный вопрос.Я знаю Oracle намного лучше, чем MySQL, поэтому я смог заставить его работать в Oracle.Может быть, лучше, но это то, что я придумал.

select count(col1) as cnt, col1, min(col2) as smallestCol2
from (
  select col1, col2, col2-rnk as rnk
  from 
  (
    select col1, col2, RANK() OVER (PARTITION by col1 order by col2 asc) as rnk
    from tmp_tbl
  )
)
group by col1,rnk
order by min(col2) desc

Я не совсем уверен, как работают ранги и разделы в MySQL, но это может быть полезно:

Функция ранга в MySQL

РЕДАКТИРОВАНИЕ : Чтобы уточнить, что происходит в моем запросе:

Внутренний запрос назначает уникальный счетчик (RNK) каждомузначение в столбце 1. Результат самого внутреннего запроса:

COL1 COL2   RNK
23   3      1
26   8      1
65   4      1
65   5      2
65   6      3
65   7      4
124  0      1
124  1      2
124  2      3
124  9      4
124  10     5
124  11     6
124  12     7

Вычитая ранг из столбца 2, вы можете получить уникальное значение для каждой группировки значений столбца 1.Результат второго вложенного запроса:

COL1 COL2  RNK
23   3     2
26   8     7
65   4     3
65   5     3
65   6     3
65   7     3
124  0     -1
124  1     -1
124  2     -1
124  9     5
124  10    5
124  11    5
124  12    5

Затем вы можете сгруппировать по столбцу 1 и этому уникальному значению.Окончательный результат:

CNT COL1 SMALLESTCOL2
4   124  9
1   26   8
4   65   4
1   23   3
3   124  0
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...