в группе сортирует в MySQL - PullRequest
       50

в группе сортирует в MySQL

2 голосов
/ 06 декабря 2011

У меня есть набор данных панели: то есть times, ids и values. Я хотел бы сделать ранжирование на основе значения для каждой даты. Я могу добиться такого рода очень просто, запустив:

select * from tbl order by date, value

У меня возникает проблема, когда таблица сортируется таким образом, как мне получить номер строки каждой группы (то есть, для каждой даты, которую я хотел бы, чтобы был столбец с рейтингом, который идет от 1 до N ).

Пример:

Введите:

Date, ID, Value
 d1, id1, 2
 d1, id2, 1
 d2, id1, 10
 d2, id2, 11

Выход:

Date, ID, Value, Rank
 d1, id2, 1, 1
 d1, id1, 2, 2
 d2, id1, 10, 1
 d2, id2, 11, 2

Ответы [ 3 ]

3 голосов
/ 06 декабря 2011

При отсутствии оконных функций вы можете заказать tbl и использовать пользовательские переменные для вычисления ранга по вашим разделам (значениям «даты»):

SELECT "date",                                                -- D) Desired columns
       id,
       value,
       rank
  FROM (SELECT "date",                                        -- C) Rank by date
               id,
               value,
               CASE COALESCE(@partition, "date")
                 WHEN "date" THEN @rank := @rank + 1
                 ELSE             @rank := 1
               END AS rank,
               @partition := "date" AS dummy
          FROM (SELECT @rank := 0 AS rank,                    -- A) User var init
                       @partition := NULL AS partition) dummy
               STRAIGHT_JOIN
               (  SELECT "date",                              -- B) Ordering query
                         id,
                         value
                    FROM tbl
                ORDER BY date, value) tbl_ordered;

Обновление

Итак, чтоэтот запрос выполняет?

Мы используем пользовательские переменные , чтобы "перебрать" отсортированный набор результатов, увеличивая или сбрасывая счетчик (@rank) в зависимости от того, какой непрерывный сегмент результатаset (отслеживается в @partition), в котором мы находимся.

В запросе A мы инициализируем две пользовательские переменные.В запросе B мы получаем записи вашей таблицы в нужном нам порядке: сначала по дате, а затем по значению. A и B вместе составляют производную таблицу, tbl_ordered, которая выглядит примерно так:

rank | partition | "date" |  id  | value 
---- + --------- + ------ + ---- + -----
  0  |   NULL    |   d1   |  id2 |    1
  0  |   NULL    |   d1   |  id1 |    2
  0  |   NULL    |   d2   |  id1 |   10
  0  |   NULL    |   d2   |  id2 |   11

Помните, нам на самом деле все равно,столбцы dummy.rank и dummy.partition - это просто случайность того, как мы инициализируем переменные @rank и @partition.

В запросе C мы перебираем записи производной таблицы,То, что мы делаем, более или менее соответствует следующему псевдокоду:

rank      = 0
partition = nil

foreach row in fetch_rows(sorted_query):
  (date, id, value) = row

  if partition is nil or partition == date:
    rank += 1
  else:
    rank = 1

  partition = date

  stdout.write(date, id, value, rank, partition)

Наконец, запрос D проецирует все столбцы из C за исключением для столбца, содержащего @partition (который мы назвали dummy и не нужно отображать).

1 голос
/ 20 марта 2013

Я знаю, что это старый вопрос, но вот более короткий ответ:

SELECT w.*, if(
      @preDate = w.date,
      @rank := @rank + 1,
      @rank := (@preDate :=w.date) = w.date
    ) rank
FROM tbl w
JOIN (SELECT @preDate := '' )a
ORDER BY date, value
0 голосов
/ 06 декабря 2011

Это бы сработало?

select [DATE],ID,Value, 
(DENSE_RANK()  OVER (   
   PARTITION BY ID
 ORDER BY Date) )AS [DenseRank],    
ROW_NUMBER() OVER ( PARTITION BY ID ORDER BY [Date] DESC) AS RN     
from SomeTable 
...