2015-06-17 3 views
0

У меня есть таблица (назовем ее mytable) с приведенной ниже структурой. В таблице ежедневно записывается около 1 миллиона строк.sql: Получение 3 наивысших значений из таблицы в формате столбца

id  date  timestamp licenseid storeid deviceid value 
1  2015-06-12 17:36:15 lic0001  1   0add  52 
2  2015-06-12 17:36:15 lic0002  1   0add  54 
3  2015-06-12 17:36:15 lic0003  1   0add  53 
4  2015-06-12 17:36:21 lic0001  1   0add  54 
5  2015-06-12 17:36:21 lic0002  1   0add  59 
6  2015-06-12 17:36:21 lic0003  1   0add  62 
7  2015-06-12 17:36:21 lic0004  1   0add  55 
8  2015-06-12 17:36:15 lic0001  1   0bdd  53 
9  2015-06-12 17:36:15 lic0002  1   0bdd  52 
10 2015-06-12 17:36:15 lic0003  1   0bdd  52 
11 2015-06-12 17:36:15 lic0004  1   0bdd  50 
12 2015-06-12 17:36:33 lic0002  1   0bdd  54 
13 2015-06-12 17:36:33 lic0003  1   0bdd  54 
14 2015-06-12 17:36:33 lic0004  1   0bdd  55 
15 2015-06-12 17:36:33 lic0005  1   0bdd  60 

Мне нужно использовать те же данные выше и получить данные, как показано ниже. Какой sql-запрос следует использовать для получения нижеследующего вывода, но я хочу только три самых высоких значения с соответствующим устройством. Я знаю, что нужно использовать стержень, но у меня возникает трудности, обрамление правильного запроса

id date  timestamp deviceid storeid deviceid1 deviceid2 deviceid3 value1 value2 value3 
1 2015-06-12 17:36:15  0add  1  lic001  lic002  lic003  52  54  53  
2 2015-06-12 17:36:21  0add  1  lic002  lic003  lic004  59  62  55 
3 2015-06-12 17:36:15  0bdd  1  lic001  lic002  lic003  53  52  52  
4 2015-06-12 17:36:33  0bdd  1  lic002  lic004  lic005  54  55  60 

Для последней строки запроса может либо вернуть lic002 или lic003, поскольку оба значения совпадают.

ответ

1

Если приемлемо для вас, самый простой способ, вероятно, использовать group_concat() и substring_index():

select min(id) as id, date, timestamp, storeid, 
     substring_index(group_concat(device order by value desc), ',', 3) as devices, 
     substring_index(group_concat(value order by value desc), ',', 3) as values 
from mytable t 
group by date, timestamp, storeid; 

Это ставит три значения в одном столбце. Вы могли бы разделить их на отдельные столбцы, если хотите.

В противном случае вам нужно перечислить значения, и это становится сложным - с одним запросом вам нужен либо подзапрос/не equijoin (возможно, очень дорогостоящий по вашему размеру данных), либо переменные.

+0

«В противном случае ...» - Неплохо, если вы используете [технику в своем блоге] (http://mysql.rjweb.org/doc.php/groupwise_max#top_n_in_each_group). –

+0

@RickJames. , , Конкретный код в вашем блоге небезопасен, потому что у вас есть несколько назначений переменных в 'select', а логика зависит от порядка оценки выражений. MySQL не гарантирует порядок оценки выражений. Однако, если эта версия не соответствует потребностям OP, тогда есть другие методы. –

+0

@GordonLinoff Зачем нам нужен min (id) здесь? Также я вижу, что запрос работает до некоторой степени, но не ограничивает его 3 значениями, и разделитель также не может быть изменен, чтобы сказать что-то вроде |. – fheo

Смежные вопросы