-1

ループのインデックス番号を計算して出力するために、値が循環する列 (つまり、1,2,3,1,2,3,1,2,3....) を使用するにはどうすればよいですか? たとえば、この簡略化された表では...

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

どうすればこれを入手できますか?

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

実際、私が管理しようとしたテーブルははるかに大きい (数百万レコード x 160 列) ため、複数の解決策がある場合は、より効率的な解決策を聞きたいです...ありがとう。

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、数値が期待されるコンテキスト (算術式のコンテキストなど) で暗黙的に数値に変換されます。より具体的には、1fortrueおよび0forに変換されfalseます。したがって、 is が(つまり、前の行の) にcir等しい限り、式は本質的に と同等ですが、とが異なる場合 (つまり、新しいグループに遭遇したことを意味します)、式は in factになります。つまり、列挙は今新たに始めました。@lastcircirindex@index := @index + 1cir@lastcircir@index := 0 + 1

必要に応じて、このソリューションを SQL Fiddle でテストできます。

于 2013-05-11T12:14:53.500 に答える
1

が順序付けられていると仮定するとnum1(ギャップが存在する可能性があります)、この問題を解決する 1 つの方法は、より小さい値の に対してループ番号が見つかった回数に基づいてインデックスを割り当てることです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

これを試して

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 に答える
0

次以外の cirsakes でこの自己結合を試して、それらの数を数えます。

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 に答える