忍者ブログ

VB.NET-TIPS などプログラミングについて

VB.NETのTIPS(小技集)を中心に、Javascript、PHP その他のプログラミングについて少し役に立つ情報を発信します。いわゆる個人的な忘備録ですが、みなさんのお役に立てれば幸いです。

MySQL 仮想連番のテーブルを生成する方法について

比較的大きな仮想連番の作成方法について説明します。

仮想的に数千~数万件の連番を返すテーブルを取得する SELECT のSQLを作成してみます。
ネットなどでは以下の様な感じで、例が載っています。
information_schema.COLUMNS はMySQLが持っているテーブル内のカラムに関する情報用のテーブルです。)

select @no := @no + 1 as no
from (select @no := 0) as dmy, information_schema.COLUMNS
limit 10;

このSQLを実行すると以下の様になります。

MariaDB [test]> select @no := @no + 1 as no
    -> from (select @no := 0) as dmy, information_schema.COLUMNS
    -> limit 10
    -> ;
+------+
| no   |
+------+
|    1 |
|    2 |
|    3 |
|    4 |
|    5 |
|    6 |
|    7 |
|    8 |
|    9 |
|   10 |
+------+
10 rows in set (0.14 sec)

information_schema.COLUMNS テーブルと「dmy」テーブルの直積のSQLですが、「dmy」は1件しかないので、 information_schema.COLUMNS がもつレコードが全て対象となります。

この方法には少々問題があります。 information_schema.COLUMNS のレコード数には限界があるからで、 実際、私がテストで使っているMySQLでは以下の様に6333件となり、この件数が限界となります。

MariaDB [(none)]> SELECT count(*) FROM information_schema.COLUMNS;
+----------+
| count(*) |
+----------+
|     6333 |
+----------+
1 row in set (7.27 sec)

もう少し、仮想連番テーブルの最大番号を大きくし、制御できる様に考えてみます。
information_schema.COLUMNS は必ずどのデータベースにも存在するので、これを利用するのですが、 information_schema.COLUMNS から10件ずつ取得したものから連番を発生させるサブクエリを2個用意して、 それらの直積を取る形で、仮想連番テーブル用の元テーブルとします。

文章で説明してもピンときませんので、以下のSQLを見て下さい。

SELECT * FROM (
    (select @no1 := @no1 + 1 as no1 from (select @no1 := 0) as dmy, information_schema.COLUMNS limit 10) X
   ,(select @no2 := @no2 + 1 as no2 from (select @no2 := 0) as dmy, information_schema.COLUMNS limit 10) X1
);


これを実行すると以下の様に「10×10」のデータが表示されます。

MariaDB [(none)]> SELECT * FROM (
    ->     (select @no1 := @no1 + 1 as no1 from (select @no1 := 0) as dmy, information_schema.COLUMNS limit 10) X
    ->    ,(select @no2 := @no2 + 1 as no2 from (select @no2 := 0) as dmy, information_schema.COLUMNS limit 10) X1
    -> );
+------+------+
| no1  | no2  |
+------+------+
|    1 |    1 |
|    2 |    1 |
|    3 |    1 |
|    4 |    1 |
|    5 |    1 |
|    6 |    1 |
|    7 |    1 |
|    8 |    1 |
|    9 |    1 |
|   10 |    1 |
|    1 |    2 |
|    2 |    2 |
|    3 |    2 |

... (省略) ...

|    7 |   10 |
|    8 |   10 |
|    9 |   10 |
|   10 |   10 |
+------+------+
100 rows in set (0.30 sec)

このクエリを元にして、仮想連番テーブルを生成するSQLを作ると以下の様になります。

SELECT @no := @no + 1 AS idx
FROM (select @no := 0) as dmy,
(
    SELECT * FROM (
            (select @no1 := @no1 + 1 as no1 from (select @no1 := 0) as dmy, information_schema.COLUMNS limit 10) X
           ,(select @no2 := @no2 + 1 as no2 from (select @no2 := 0) as dmy, information_schema.COLUMNS limit 10) X1
    ) 
) XX
LIMIT 10;


これを実行すると以下の様に1~10の連番を返すことができます。

MariaDB [(none)]> SELECT @no := @no + 1 AS idx
    -> FROM (select @no := 0) as dmy,
    -> (
    ->     SELECT * FROM (
    ->             (select @no1 := @no1 + 1 as no1 from (select @no1 := 0) as dmy, information_schema.COLUMNS limit 10) X
    ->            ,(select @no2 := @no2 + 1 as no2 from (select @no2 := 0) as dmy, information_schema.COLUMNS limit 10) X1
    ->     )
    -> ) XX
    -> LIMIT 10;
+------+
| idx  |
+------+
|    1 |
|    2 |
|    3 |
|    4 |
|    5 |
|    6 |
|    7 |
|    8 |
|    9 |
|   10 |
+------+
10 rows in set (0.25 sec)

サブクエリの LIMIT で生成されるデータ数の最大を決定していますが、この値を「100」にすれば最大は「10000」になります。 また、サブクエリの SELECT 文を更に追加して以下の様にすれば「10×10×10×10」が最大となります。
さらに「10」のところを「100」にすれば1億までの連番を返すことができます。(そこまでの必要性はありませんが)

SELECT @no := @no + 1 AS idx
FROM (select @no := 0) as dmy,
(
    SELECT * FROM (
            (select @no1 := @no1 + 1 as no1 from (select @no1 := 0) as dmy, information_schema.COLUMNS limit 10) X
           ,(select @no2 := @no2 + 1 as no2 from (select @no2 := 0) as dmy, information_schema.COLUMNS limit 10) X1
           ,(select @no3 := @no3 + 1 as no3 from (select @no3 := 0) as dmy, information_schema.COLUMNS limit 10) X2
           ,(select @no4 := @no4 + 1 as no4 from (select @no4 := 0) as dmy, information_schema.COLUMNS limit 10) X3
    ) 
) XX
LIMIT 10;











PR

コメント

コメントを書く