Вернуть набор результатов в числовом шаблоне / последовательности - PullRequest
0 голосов
/ 04 сентября 2010

У меня проблема в том, чтобы получить набор результатов в числовом шаблоне / последовательности на основе значения одного столбца.

Скажите, у меня есть следующая таблица:

+-------+  
| val   |  
+-------+
| 1     |
| 1     |
| 1     |
| 1     |
| 2     |
| 2     |
| 2     |
| 2     |
| 3     |
| 3     |
| 3     |
| 3     |
+-------+

Как мне сделать это вместо этого:

+-------+  
| val   |  
+-------+
| 1     |
| 2     |
| 3     |
| 1     |
| 2     |
| 3     |
| 1     |
| 2     |
| 3     |
| 1     |
| 2     |
| 3     |
+-------+

Случай, упомянутый Аулароном:

Что, если одного из значений недостаточно для заполнения пробелов, каково ожидаемое поведение? Скажем, мы заменим два из 3 на 8

+-------+  
| val   |  
+-------+
| 1     |
| 1     |
| 1     |
| 1     |
| 2     |
| 2     |
| 2     |
| 2     |
| 3     |
| 3     |
| 8     |
| 8     |
+-------+

Я бы по-прежнему ожидал, что он будет идти в числовой последовательности сначала наименьший, затем наибольший, затем наименьший, затем наибольший

+-------+  
| val   |  
+-------+
| 1     |
| 2     |
| 3     |
| 8     |
| 1     |
| 2     |
| 3     |
| 8     |
| 1     |
| 2     |
| 1     |
| 2     |
+-------+

1 Ответ

1 голос
/ 04 сентября 2010

Это то, что мы называем крупным rownum хаком. Допустим, ваша таблица называется t, а столбец значений - val. Это даст результат, который вы ищете.

SELECT val    /* step 6 */
FROM
(SELECT A.val, 
   CASE 
   WHEN A.val <> IFNULL(B.val,-1) THEN @q:=0   /* step 4 */
   ELSE @q:=@q+1                               /* step 4 */ 
    END AS seq                                 /* step 4 */
   FROM
    (SELECT @q:=0)r,
    (SELECT                          /* step 1 */
            @a:=@a+1 AS n,           /* step 1 */
            val                      /* step 1 */
      FROM  (SELECT @a:= 0)r, T      /* step 1 */
     ORDER BY val) A                 /* step 1 */
   LEFT JOIN
    (SELECT                        /* step 2, like step 1 */
            @b:=@b+1 AS n, 
            val
       FROM  (SELECT @b:= 0)r, T
     ORDER BY val) B
    ON B.n = A.n-1    /* step 3 */
 ORDER BY seq,val) s  /* step 5 */

Слово или два объяснения:

  1. Нам нужно превратить вашу таблицу val в val, n table (где n - строка номер)

  2. Тогда нам нужно два из них, с номера независимых строк @a и @ b

  3. Тогда нам нужно объединить их со смещением row = row-1 для сравнения соседние столбцы val.

  4. Тогда нам нужно применить последовательность номер каждого столбца val, что перезагружается. То есть нам нужно дать порядковые номера от 1,2,3 до 1, затем 2s, и т.д.

  5. Затем нам нужно отсортировать по seq, затем Вэл.

  6. Тогда нам нужно скрыть последовательность.

О чудо ....

Взломать взломать!

...