-1

How can I use a column whose values are circular (i.e. 1,2,3,1,2,3,1,2,3....) to calculate and output the index number of the loop? So for example in this simplified table...

num cir
1    1
2    2
3    3
4    1
5    2
6    3
7    1
8    2
9    3

How can I get this?

num cir index
1    1    1
2    2    1
3    3    1
4    1    2
5    2    2
6    3    2
7    1    3
8    2    3
9    3    3

Actually, a table I tried to manage is much bigger (millions of records times 160 columns), so if there are multiple solutions I'd like to hear more efficient ones... Thanks.

4

4 回答 4

3

Gordon Linoff 是对的:在 SQL 中,表确实没有内在的顺序。但是,仍然有一种方法可以在您的情况下分配索引。唯一的问题是,顺序是不确定的,并且 1 可能与 2 组合在一起,而 2 不一定是它后面的那个(以您可能期望的任何特定顺序)。也就是说,最终结果可能类似于您的示例:

num  cir  index
---  ---  -----
1    1    1
2    2    1
3    3    1
4    1    2
5    2    2
6    3    2
7    1    3
8    2    3
9    3    3

但它很可能是这样的:

num  cir  index
---  ---  -----
7    1    1
2    2    1
3    3    1
4    1    2
8    2    2
6    3    2
1    1    3
5    2    3
9    3    3

如果num正如您所说的那样,它不是“有序的”(因此,我假设它不能用于排序)。

cir这个想法是仅对列上的数据集进行排序

num  cir
---  ---
1    1
4    1
7    1
2    2
5    2
8    2
3    3
6    3
9    3

然后使用变量赋值来生成index

num  cir                index
---  ---                -----
1    1    1             1
4    1    2             2
7    1    3             3
2    2       1     ->   1
5    2       2          2
8    2       3          3
3    3          1       1
6    3          2       2
9    3          3       3

就是这样:

SELECT
  num,
  cir,
  `index`
FROM (
  SELECT
    num,
    @index := @index * (cir = @lastcir) + 1 AS `index`,
    @lastcir := cir AS cir
  FROM
    yourtable,
    (SELECT @index := 0, @lastcir := 0) v
  ORDER BY
    cir
) s
ORDER BY
  `index`,
  cir
;

可以猜到,这个表达式

@index := @index * (cir = @lastcir) + 1

是分配索引的那个。基本上,如果你删除* (cir = @lastcir)部分,你会得到

@index := @index + 1

这可能不需要解释:它只是增加@index值。

每次cir遇到新值时,该附加位都会重置枚举(请记住,数据集按 排序cir)。在 MySQL 中,布尔表达式,如cir = @lastcir,在需要数字的上下文中隐式转换为数字,例如算术表达式的上下文。更具体地说,它被转换为1fortrue0for false。因此,只要cir等于@lastcir(即前一行的)cir,表达式本质index上等于现在重新开始。@index := @index + 1cir@lastcircir@index := 0 + 1

如果您愿意,可以在 SQL Fiddle测试此解决方案。

于 2013-05-11T12:14:53.500 回答
1

假设它num1是有序的(尽管可能存在间隙),解决此问题的一种方法是根据为较小的值找到循环编号的次数来分配索引num。我认为在 MySQL 中执行此操作的最清晰方法是使用相关子查询:

select t.*,
       (select count(*) from t t2 where t2.cir = t.cir and t2.num <= t.num
       ) as `index`
from t

如果num未订购,那么您有问题。SQL 表本质上是无序的,因此对于给定的行没有“之前”和“之后”的概念。也就是说,除非您有某种方式对结果进行排序,否则没有一种可靠的方法来分配索引。

于 2013-05-10T19:38:17.847 回答
0

尝试使用非下一个 cirsake 进行自我加入并计算它们:

SELECT t1.num AS num, t1.cir AS cir, COUNT(*) AS index
  FROM t AS t1 JOIN t AS t2 on t2.cir = t1.cir AND t2.num <= t1.num
  GROUP BY t1.num, t1.cir
;
于 2013-05-10T20:04:29.613 回答
0

尝试这个

SELECT 
  num,
  cir,
  @row_num := IF(@prev_cir<cir,@row_num,@row_num+1) as cir_index,
  @prev_cir:= cir
FROM 
(SELECT @row_num := 0) r
JOIN (
    SELECT 
      num, 
      cir 
    FROM 
      mytable 
    ORDER BY
      num
) t

首先,我确保记录按num. 然后我检查前一个cir与当前一个。如果前一个cir大于当前,我增加cir_index

SQLFIDDLE

于 2013-05-11T12:35:12.900 回答