在SQL Server中有循环函数的方法吗

wf82jlnq  于 2023-02-03  发布在  SQL Server
关注(0)|答案(2)|浏览(248)

我正在尝试编写查询,可以循环新列到选定的数字,如100或200个新列,这使用的数据从以前创建的列。
我有如下数据:

IF NOT EXISTS 
(
    SELECT * FROM sysobjects WHERE name = 'test' AND xtype = 'U'
) 
CREATE TABLE test 
(
    [id] INT,
    [a] NUMERIC(3, 2),
    [b] NUMERIC(3, 2)
);

INSERT INTO test 
VALUES (1, 0.1, 0.7),
       (2, 0.5, 0.5),
       (3, 0.5, 0.3),
       (4, 0.6, 0.5),
       (5, 0.5, 0.5),
       (6, 0.5, 0.67),
       (7, 0.5, 0.5),
       (8, 0.46, 0.5),
       (9, 0.5, 0.5),
       (10, 0.37, 0.52),
       (11, 0.37, 0.37),
       (12, 0.28, 0.2);

我有id、a和B作为输入,并且我想创建新列,如cc = a+b,然后d = a+b+c等等,甚至100或200个新列。
我可以使用下面这样的查询,但是如果我需要100列,就需要花很长时间来编写。

select 
    t.*,
    t.a + t.b + t.c d
from
    (select 
         *, 
         a + b c 
     from test) t;

我知道SQL不擅长循环,但如果可能的话我还是想试试。谢谢。

vyswwuz2

vyswwuz21#

你的问题的细节表明数据库设计很糟糕,你永远不想像那样对列求和,但是你的问题是,在SQL中,你是否可以告诉它自己写,这样它就可以保存你输入所有的东西,通常是否定的。
在某些情况下,数据库系统将支持类似EXCEPT的东西(或者因为Snowflake喜欢与众不同,所以支持EXCLUDE
这很有帮助,因为你可以使用SELECT * EXCEPT col1,这正是你所需要的,尽管你想用SUM来做这件事。
一般来说,不,这种语言不支持这样的事情。在某些情况下,你可能会很幸运,RDBMS为很多用户想做的事情添加了一个有用的函数(比如EXCEPT的情况)
因此,如果你真的想这么做,你就必须跳出SQL自己去构建它,就我个人而言,我通过jinja引擎运行我的SQL,它会为我解析出SQL。
实际上,我有一个定制的 Package 器,它完全符合您的要求:

SELECT *,
       ({{ variables | join(' + ') }}) AS SUM_OF_ALL
FROM {{ source_table }}

本质上这是一个函数,我必须传递一个列名列表给它--所以如果我有200个列名列表,它仍然会很烦人,但是使用宏和其他东西,让它动态地找到所有列名是绝对可能的,这样就不必显式地声明它们。
TL;DR -不,不离开SQL是不可能的。

zfciruhq

zfciruhq2#

给你:

IF NOT EXISTS 
(
    SELECT  * FROM  sysobjects WHERE    name = 'test' AND xtype = 'U'
) 
CREATE TABLE test 
(
    [id] INT,
    [a] NUMERIC(3, 2),
    [b] NUMERIC(3, 2)
);

INSERT INTO test 
VALUES (1, 0.1, 0.7),
       (2, 0.5, 0.5),
       (3, 0.5, 0.3),
       (4, 0.6, 0.5),
       (5, 0.5, 0.5),
       (6, 0.5, 0.67),
       (7, 0.5, 0.5),
       (8, 0.46, 0.5),
       (9, 0.5, 0.5),
       (10, 0.37, 0.52),
       (11, 0.37, 0.37),
       (12, 0.28, 0.2);

DECLARE @sql nvarchar(max) = 'select t.*'

;WITH cte AS (
SELECT  TOP 100 row_number() OVER(ORDER BY (SELECT  NULL)) AS cnt
FROM    sys.objects so CROSS JOIN sys.columns sc
)
SELECT  @sql = @sql + '
, 0' + '+ (t.a + t.b) * (POWER(2.0, ' + CAST(c.cnt  as varchar(30)) + '-1))  as c' + cast(c.cnt AS varchar(300))
FROM    cte c

SELECT  @sql = @sql + ' from test t'
SELECT  @sql
EXEC    (@sql)

编辑:这段代码循环100列左右,并在一个新列中生成前一列的总和。过一段时间后,总和变得相当大。也许我做错了什么,但不确定:)

相关问题