以数字模式/序列返回结果集

时间:2010-09-04 09:33:26

标签: mysql design-patterns sequence resultset

我手头有问题,那就是根据单个列的值以数字模式/序列获取结果集。

说我有下表:

+-------+  
| 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     |
+-------+

aularon提到的案例:

如果其中一个值不足以填补空白,那么预期的行为是什么呢?假设我们将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 个答案:

答案 0 :(得分:1)

这就是我们所谓的主要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表(其中n是行 数)

  2. 然后我们需要其中两个 独立行号@a和@b

  3. 然后我们需要将它们连接在一起 使用row = row-1偏移量进行比较 相邻的val列。

  4. 然后我们需要应用一个序列 每个val列的编号,即 复位。也就是说,我们需要给予 序列号1,2,3到1s,然后是2s, 等

  5. 然后我们需要按seq排序 VAL。

  6. 然后我们需要隐藏seqs。

  7. 看见......

    Hack hack!