在SQL中分配新的局部变量要求

在SQL中分配新的局部变量要求,sql,sql-server,Sql,Sql Server,我不熟悉在SQL中使用DECLARE、SET和EXEC(),所以我的方法可能不适合这个问题,所以请耐心听我说。我的目标是减少重复代码的使用。我现在有很多联合声明,其中where子句是累积的。部分代码如下所示(对于本文来说太长): 编辑1:初始代码 -- step 1 select 1 as step, sum(Amount) as totalValue, count(*) as total, 'comment 1' as comment from table_A Where requi

我不熟悉在SQL中使用DECLARE、SET和EXEC(),所以我的方法可能不适合这个问题,所以请耐心听我说。我的目标是减少重复代码的使用。我现在有很多联合声明,其中where子句是累积的。部分代码如下所示(对于本文来说太长):

编辑1:初始代码

-- step 1
select 1 as step, sum(Amount) as totalValue, count(*) as total, 'comment 1' as comment
from table_A
Where 
    requirement1 = 1
    and requirement2 = 100
    and requirement3 = 'A'
-- step 2
union
select 2 as step, sum(Amount) as totalValue, count(*) as total, 'comment 2' as comment
from table_A
Where 
    requirement1 = 1
    and requirement2 = 100
    and requirement3 = 'A'
    and requirement4 = 50
union
.
.
.
-- step n
union
select n as step, sum(Amount) as totalValue, count(*) as total, 'comment n' as comment
from table_A
Where 
    requirement1 = 1
    and requirement2 = 100
    and requirement3 = 'A'
    and requirement4 = 50
    .
    .
    .
    requirementn = 5
编辑1:我正在努力实现的目标

+------+-------------+-------+------------+
| step | totalAmount | total |  comment   |
+------+-------------+-------+------------+
| 1    |      10000  |    50 | comment 1  |
| 2    |        5000 |   100 | comment 2  |
| 3    |        2000 |   500 | comment 3  |
| .    |           . |     . | .          |
| .    |           . |     . | .          |
| .    |           . |     . | .          |
| n    |        5000 |    10 | comment n  |
+------+-------------+-------+------------+
编辑1:我如何尝试解决问题

我已经到了可以使用局部变量将新需求添加到前一个需求的地步。但是,我无法确定是否有可能对已设置的变量进行某种重新赋值。因此,我只能获得步骤1的步骤计数和注释,而不是每个步骤的新名称。我在出现问题的地方添加了注释。我的代码如下所示:

    -- general selection requirements
    DECLARE @selectedOverview varchar(1000)
    -- requirements step 1
    DECLARE @stepRequirement1 varchar(1000)
    DECLARE @step varchar(50)
    DECLARE @comment varchar(100)
    DECLARE @requirement1 varchar(1)
    DECLARE @requirement2 varchar(100)
    DECLARE @requirement3 varchar(100)
    SET @step = 1
    SET @comment = 'Total overview'
    SET @requirement1 = 1 
    SET @requirement2 = 100
    SET @requirement3 = 'A'
    -- additional requirements step 2
    DECLARE @stepRequirement2 varchar(1000)
    DECLARE @requirement4 varchar(100)
    SET @requirement4 = 50


    -- dynamic selection
    SET
        @selectedOverview = 
            'select 
                ' + @step + ' as step
                ,sum(totalamount) as beløb
                ,count(*) as antal
                ,' + '''' + @comment + '''' + ' as comment
            from KONVICI.dbo.A_MATRIX 
                where ' 

    -- step2
    SET 
    @stepRequirement1 = 
        @selectedOverview
        +
         'requirement1 = ' + @requirement1
        + 
        ' and requirement2 = ' + @requirement2  
        +
        ' and requirement3 = '  + '''' + @requirement3 + ''''
    EXEC(@stepRequirement3)
    -- step 2
    SET @comment = 'one layer has been removed' -- **PROBLEM: the re-assignment is not working**
    SET @step = @step + 1 -- **PROBLEM: @step is not incremented by 1**
    SET 
    @stepRequirement2 = 
        @stepRequirement1 
        + 
        ' and requirement4 = ' + @requirement4 
    EXEC(@stepRequirement2) .
.
.
-- step n goes here
-- the same approach as for step2
-- drop tables if they exists
drop table if exits #table_step1
drop table if exits #table_step2
...

-- select data from the different steps
-- select data step 1
select *
into #table_step1
from table_A
where
    requirement1 = 1
    and requirement2 = 100
    and requirement3 = 'A'

-- select data step 2
select * 
into #table_step2
from #table_step1
where 
    requirement4 = 50
...

-- aggregate the data for each step and use UNION ALL to get overall overview
select 1 as step, sum(Amount) as totalValue, count(*) as total, 'comment 1' as comment
from #step1

UNION ALL

select 2 as step, sum(Amount) as totalValue, count(*) as total, 'comment 2' as comment

UNION ALL
... 

你可以用CTE简化一下

WITH CTE as (
SELECT sum(Amount) as totalValue, count(*) as total
from table_A
)

SELECT 1, comment = 'comment 1', * FROM CTE 
WHERE     requirement1 = 1
    and requirement2 = 100
    and requirement3 = 'A'

UNION ALL

SELECT 2, comment = 'comment 2', * FROM CTE    
    where requirement1 = 2
    and requirement2 = 100
    and requirement3 = 'A'
    and requirement4 = 50
...

没有动态SQL。

您可以使用CTE简化一点

WITH CTE as (
SELECT sum(Amount) as totalValue, count(*) as total
from table_A
)

SELECT 1, comment = 'comment 1', * FROM CTE 
WHERE     requirement1 = 1
    and requirement2 = 100
    and requirement3 = 'A'

UNION ALL

SELECT 2, comment = 'comment 2', * FROM CTE    
    where requirement1 = 2
    and requirement2 = 100
    and requirement3 = 'A'
    and requirement4 = 50
...
没有动态SQL。

我的想法(请原谅语法错误,我的想法很清楚)是用case-when语句替换联合以获得步骤,这将简化事情,因为所有数据都来自同一个表,并且只用于计算步骤值

只要确保在某些布尔条件重叠时使用正确的表达式顺序即可

例如

我的想法(请原谅我的语法错误,这个想法很清楚)是用case-when语句替换联合以获得步骤,这将简化事情,因为所有数据都来自同一个表,只用于计算步骤值

只要确保在某些布尔条件重叠时使用正确的表达式顺序即可

例如


一种非常简单的方法是使用临时表,然后添加额外的WHERE语句。这还增加了能够看到满足每个步骤标准的所有观察结果的好处。代码可能如下所示:

    -- general selection requirements
    DECLARE @selectedOverview varchar(1000)
    -- requirements step 1
    DECLARE @stepRequirement1 varchar(1000)
    DECLARE @step varchar(50)
    DECLARE @comment varchar(100)
    DECLARE @requirement1 varchar(1)
    DECLARE @requirement2 varchar(100)
    DECLARE @requirement3 varchar(100)
    SET @step = 1
    SET @comment = 'Total overview'
    SET @requirement1 = 1 
    SET @requirement2 = 100
    SET @requirement3 = 'A'
    -- additional requirements step 2
    DECLARE @stepRequirement2 varchar(1000)
    DECLARE @requirement4 varchar(100)
    SET @requirement4 = 50


    -- dynamic selection
    SET
        @selectedOverview = 
            'select 
                ' + @step + ' as step
                ,sum(totalamount) as beløb
                ,count(*) as antal
                ,' + '''' + @comment + '''' + ' as comment
            from KONVICI.dbo.A_MATRIX 
                where ' 

    -- step2
    SET 
    @stepRequirement1 = 
        @selectedOverview
        +
         'requirement1 = ' + @requirement1
        + 
        ' and requirement2 = ' + @requirement2  
        +
        ' and requirement3 = '  + '''' + @requirement3 + ''''
    EXEC(@stepRequirement3)
    -- step 2
    SET @comment = 'one layer has been removed' -- **PROBLEM: the re-assignment is not working**
    SET @step = @step + 1 -- **PROBLEM: @step is not incremented by 1**
    SET 
    @stepRequirement2 = 
        @stepRequirement1 
        + 
        ' and requirement4 = ' + @requirement4 
    EXEC(@stepRequirement2) .
.
.
-- step n goes here
-- the same approach as for step2
-- drop tables if they exists
drop table if exits #table_step1
drop table if exits #table_step2
...

-- select data from the different steps
-- select data step 1
select *
into #table_step1
from table_A
where
    requirement1 = 1
    and requirement2 = 100
    and requirement3 = 'A'

-- select data step 2
select * 
into #table_step2
from #table_step1
where 
    requirement4 = 50
...

-- aggregate the data for each step and use UNION ALL to get overall overview
select 1 as step, sum(Amount) as totalValue, count(*) as total, 'comment 1' as comment
from #step1

UNION ALL

select 2 as step, sum(Amount) as totalValue, count(*) as total, 'comment 2' as comment

UNION ALL
... 

一种非常简单的方法是使用临时表,然后添加额外的WHERE语句。这还增加了能够看到满足每个步骤标准的所有观察结果的好处。代码可能如下所示:

    -- general selection requirements
    DECLARE @selectedOverview varchar(1000)
    -- requirements step 1
    DECLARE @stepRequirement1 varchar(1000)
    DECLARE @step varchar(50)
    DECLARE @comment varchar(100)
    DECLARE @requirement1 varchar(1)
    DECLARE @requirement2 varchar(100)
    DECLARE @requirement3 varchar(100)
    SET @step = 1
    SET @comment = 'Total overview'
    SET @requirement1 = 1 
    SET @requirement2 = 100
    SET @requirement3 = 'A'
    -- additional requirements step 2
    DECLARE @stepRequirement2 varchar(1000)
    DECLARE @requirement4 varchar(100)
    SET @requirement4 = 50


    -- dynamic selection
    SET
        @selectedOverview = 
            'select 
                ' + @step + ' as step
                ,sum(totalamount) as beløb
                ,count(*) as antal
                ,' + '''' + @comment + '''' + ' as comment
            from KONVICI.dbo.A_MATRIX 
                where ' 

    -- step2
    SET 
    @stepRequirement1 = 
        @selectedOverview
        +
         'requirement1 = ' + @requirement1
        + 
        ' and requirement2 = ' + @requirement2  
        +
        ' and requirement3 = '  + '''' + @requirement3 + ''''
    EXEC(@stepRequirement3)
    -- step 2
    SET @comment = 'one layer has been removed' -- **PROBLEM: the re-assignment is not working**
    SET @step = @step + 1 -- **PROBLEM: @step is not incremented by 1**
    SET 
    @stepRequirement2 = 
        @stepRequirement1 
        + 
        ' and requirement4 = ' + @requirement4 
    EXEC(@stepRequirement2) .
.
.
-- step n goes here
-- the same approach as for step2
-- drop tables if they exists
drop table if exits #table_step1
drop table if exits #table_step2
...

-- select data from the different steps
-- select data step 1
select *
into #table_step1
from table_A
where
    requirement1 = 1
    and requirement2 = 100
    and requirement3 = 'A'

-- select data step 2
select * 
into #table_step2
from #table_step1
where 
    requirement4 = 50
...

-- aggregate the data for each step and use UNION ALL to get overall overview
select 1 as step, sum(Amount) as totalValue, count(*) as total, 'comment 1' as comment
from #step1

UNION ALL

select 2 as step, sum(Amount) as totalValue, count(*) as total, 'comment 2' as comment

UNION ALL
... 

我不太理解这里的初始查询,但是,如果所有数据都来自同一个表(
table\u A
),为什么需要使用
UNION
?为什么不在子句中的中使用或或类似的语句?(不知道什么是正确的,因为没有足够的细节。)此外,使用
UNION-ALL
,可能会提高性能,因为每个数据集似乎已经是唯一的了;因此,检查不同的行只会浪费SQL Server的时间(尽管如果我们可以去掉
UNION ALL
,那么这一点就没有意义了)。此外,字符串连接是一个非常糟糕的主意。SQL注入不是你的朋友。确保您的SQL参数化,或正确引用您的项目,例如使用
QUOTENAME
。也许如果您可以显示一些示例输出并解释您想使用它做什么,我们可以找到更好的方法,似乎您在添加预期结果时忘了输入示例数据。是的,但是,正如我上面所评论的,您忘记了样本数据。如果没有原始数据,我们如何向您展示如何获得预期的结果集?我不太理解这里的初始查询,但是,如果所有数据都来自同一个表(
table\u A
),为什么需要使用
UNION
?为什么不在子句中的中使用或或类似的语句?(不知道什么是正确的,因为没有足够的细节。)此外,使用
UNION-ALL
,可能会提高性能,因为每个数据集似乎已经是唯一的了;因此,检查不同的行只会浪费SQL Server的时间(尽管如果我们可以去掉
UNION ALL
,那么这一点就没有意义了)。此外,字符串连接是一个非常糟糕的主意。SQL注入不是你的朋友。确保您的SQL参数化,或正确引用您的项目,例如使用
QUOTENAME
。也许如果您可以显示一些示例输出并解释您想使用它做什么,我们可以找到更好的方法,似乎您在添加预期结果时忘了输入示例数据。是的,但是,正如我上面所评论的,您忘记了样本数据。如果没有原始数据,我们如何向您展示如何获得预期的结果集?或者更好的是,创建一个get_step()函数,该函数接受用于获取步骤的所有列,这将保留get step逻辑并简化维护。或者更好的是,创建一个get_step()函数,该函数接受用于获取步骤的所有列,这将保留获取步骤逻辑并简化维护。