简体   繁体   English

有没有办法在 SQL 服务器中循环 function

[英]Is there a way to loop function in SQL Server

I'm trying to write queries that can loop new columns to selected number, such as 100 or 200 new columns, which use data from the previously created columns.我正在尝试编写可以将新列循环到选定数字的查询,例如 100 或 200 个新列,它们使用先前创建的列中的数据。

I have data like below:我有如下数据:

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);

I have id, a, and b as input, and I want to create new columns as c c = a+b, then d = a+b+c and so on, to even 100 or 200 new columns.我有 id、a 和 b 作为输入,我想创建新列 c c = a+b,然后 d = a+b+c 等等,甚至 100 或 200 个新列。

I could use queries like the one below, but if I need 100 columns, it will take forever to write.我可以使用如下所示的查询,但如果我需要 100 列,将永远无法编写。

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

I know that SQL is not good at loops, but I still want to try if it even possible.Thank you.我知道 SQL 不擅长循环,但如果可能的话我还是想尝试一下。谢谢。

The specifics of your problem indicate the database design is terrible, you'd never want to sum across columns like that.你的问题的细节表明数据库设计很糟糕,你永远不想像这样跨列求和。 But your question about whether in SQL you can tell it to sort of write itself so that it'll save you from typing it all out, is generally no.但是你关于 SQL 中是否可以告诉它自己写,这样它就可以避免你全部输入的问题,通常是不。

In some cases, database systems will support something like EXCEPT (or since Snowflake likes to be different, EXCLUDE )在某些情况下,数据库系统将支持类似EXCEPT的东西(或者因为 Snowflake 喜欢与众不同,所以EXCLUDE

That is helpful because you can SELECT * EXCEPT col1 which is sort of what you're looking for, though you're wanting to do that with a SUM .这很有用,因为您可以SELECT * EXCEPT col1这就是您正在寻找的东西,尽管您想要使用SUM来做到这一点。

In general, no the language does not support such things.一般来说,没有语言不支持这样的事情。 You might get lucky in some cases, where an RDBMS adds a helpful function for something that lots of users want to do (like in the case of EXCEPT)在某些情况下,您可能会很幸运,其中 RDBMS 为许多用户想要做的事情添加了一个有用的 function(例如在 EXCEPT 的情况下)

Therefore, if you really want to do it, you have to look outside of SQL and build it yourself.因此,如果你真的想做,你必须在 SQL 之外寻找并自己构建它。 For me personally, I run my SQL through a jinja engine that will parse out the SQL for me.就我个人而言,我通过 jinja 引擎运行我的 SQL,该引擎将为我解析出 SQL。

I actually have a custom wrapper that does the exact thing you want:我实际上有一个自定义包装器可以完全满足您的需求:

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

This is essentially a function that I have to pass a list of column names into it - so if I had 200 it would still be annoying.这本质上是一个 function,我必须将列名列表传递给它——所以如果我有 200 个,它仍然会很烦人。 However using macros and other things it is definitely possible, to have it dynamically find all the column names so they don't have to be declared explicitly.然而,使用宏和其他东西绝对是可能的,让它动态地找到所有的列名,这样它们就不必显式声明了。

TL;DR - no, not possible without going outside of SQL. TL;DR - 不,不离开 SQL 是不可能的。

Here you go:给你go:

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)


EDIT: This code loops 100 columns or so and generate sums for previous column in a new column.编辑:此代码循环 100 列左右,并为新列中的前一列生成总和。 The sums get pretty big after a while.一段时间后,总和会变得相当大。 Maybe i'm doing something wrong but not sure:)也许我做错了什么但不确定:)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM