5

我有下表:

CREATE TABLE dummy (
  thousand INT(10) UNSIGNED,
  UNIQUE(thousand)
);

是否有我可以用来插入每千个正整数的 sql 语法,从 1 到 100 万?我可以在 php 中实现这一点,但我想知道这是否可能在不使用存储过程的情况下实现。

thousand
1
1001
2001
3001
4001
...
998001
999001
4

4 回答 4

1

不幸的是,mysql 不支持任何特殊的 SQL 函数。

您必须填充一个表,这没什么大不了的——它只有 1000 行。
您也可以将临时表与联合体拼凑在一起,但这并不优雅——不妨使用一张表。


其他数据库确实支持它,例如使用 postgres 的generate_series()功能,但这并不令人安慰。


附带说明一下,我经常发现在表格中填充从1最多到一个大数字的连续数字很方便,就像这样的场合,我只会select 1000 * num from numbers where num <= 1000.

于 2012-11-26T02:49:12.017 回答
1

对于单语句查询,即不引入任何额外的表和支持语句,我会在“伪”SQL 中使用这种方法:

SELECT (D1.Digit + D2.Digit + D3.Digit)* 1000 + 1
FROM  
(
    SELECT 0 AS Digit UNION ALL
    SELECT 1 UNION ALL
    SELECT 2 UNION ALL
    SELECT 3 UNION ALL
    SELECT 4 UNION ALL
    SELECT 5 UNION ALL
    SELECT 6 UNION ALL
    SELECT 7 UNION ALL
    SELECT 8 UNION ALL
    SELECT 9
) AS D1
CROSS JOIN 
(
    SELECT 0 AS Digit UNION ALL
    SELECT 10 UNION ALL
    SELECT 20 UNION ALL
    SELECT 30 UNION ALL
    SELECT 40 UNION ALL
    SELECT 50 UNION ALL
    SELECT 60 UNION ALL
    SELECT 70 UNION ALL
    SELECT 80 UNION ALL
    SELECT 90
) AS D2
CROSS JOIN 
(
    SELECT 0 AS Digit UNION ALL
    SELECT 100 UNION ALL
    SELECT 200 UNION ALL
    SELECT 300 UNION ALL
    SELECT 400 UNION ALL
    SELECT 500 UNION ALL
    SELECT 600 UNION ALL
    SELECT 700 UNION ALL
    SELECT 800 UNION ALL
    SELECT 900
) AS D3
WHERE ((D1.Digit + D2.Digit + D3.Digit)* 1000 + 1) < 1000000

我不是 100% 确定,但它应该在 mysql 中运行良好,或者可能需要一些小的改动。

如果您能够重用查询的部分内容,它会变得更漂亮,例如在 SQL Server 中,我将其编写如下:

WITH Digits AS
(
    SELECT 0 AS Digit UNION ALL
    SELECT 1 UNION ALL
    SELECT 2 UNION ALL
    SELECT 3 UNION ALL
    SELECT 4 UNION ALL
    SELECT 5 UNION ALL
    SELECT 6 UNION ALL
    SELECT 7 UNION ALL
    SELECT 8 UNION ALL
    SELECT 9
)
SELECT (D1.Digit + D2.Digit + D3.Digit)* 1000 + 1
FROM (SELECT Digit FROM Digits) AS D1
CROSS JOIN (SELECT Digit * 10 AS Digit FROM Digits) AS D2
CROSS JOIN (SELECT Digit * 100 AS Digit FROM Digits) AS D3
WHERE ((D1.Digit + D2.Digit + D3.Digit)* 1000 + 1) < 1000000

注意乘法发生的位置,在子查询中相乘可能比在结果表达式中更有效。

于 2012-11-26T02:49:50.190 回答
1

这是一个技巧,我通常用于这类问题,类似于@sergeBelov 解决方案:

创建一个锚表,一个临时表,并用 0 到 9 的值填充它,如下所示:

CREATE TABLE TEMP (Digit int);
INSERT INTO Temp VALUES(0),(1),(2),(3),(4),(5),(6),(7),(8),(9);

然后你可以这样做:

INSERT INTO dummy(thousand)
SELECT 1 + (id - 1) * 1000 AS n
FROM
(
  SELECT t3.digit * 100 + t2.digit * 10 + t1.digit + 1  AS id
  FROM         TEMP AS t1
  CROSS JOIN TEMP AS t2
  CROSS JOIN TEMP AS t3
) t;

SQL 小提琴演示

这是如何运作的?

您正在寻找的序列 numbers( 1, 1001, 2001, ... , 998001, 999001) 1000 项是他们所谓的Arithmetic progress,在您的情况下nth,序列 ( an) 的项由下式给出:

A + (n - 1) * d
In you sequence: a = 1, d = 1000

其中A是序列的第一项,n 是项,d 是每两项之间的差(每两个连续项相同)。

子查询:

  SELECT t3.digit * 100 + t2.digit * 10 + t1.digit + 1  AS id
  FROM         TEMP AS t1
  CROSS JOIN TEMP AS t2
  CROSS JOIN TEMP AS t3;

将生成一个从 1 到 1000 的数字列表(您的序列中的术语总数),然后我们1 + (id - 1) * 1000在外部选择中从这些数字中获取序列中的每个术语。

于 2012-11-26T02:55:21.360 回答
1
insert into dummy
   ( thousand )
select
     PreQuery.thousand 
  from
    (  select
             @sqlvar thousand,
             @sqlvar := @sqlvar + 1000
          from
             AnyTableWithAtLeast1000Records,
             ( select @sqlvar := 1 ) sqlvars
          limit 1000 ) PreQuery

您可以从 select 语句中插入。使用 MySQL 变量,从 1 开始。然后,加入系统中可能有 1000 条(或更多)记录的任何表,以生成一行。即使没有从此类表中获取任何实际列,我们也只需要它作为记录位置。然后@sqlvar 从 1 开始并在名为千的列中返回。然后,立即将 1000 添加到“AnyTable...”中的下一条记录

于 2012-11-26T03:02:19.277 回答