具有聚合函数的动态SQL(列名变量)

时间:2013-04-16 10:31:13

标签: sql sql-server dynamic

我在表中有以下列:IdRec dataora aparat1 aparat2 .... aparat100以及存储过程中的以下代码:

ALTER PROCEDURE [dbo].[GetConsumRealElQRo] 
    @id_aparat int,
    @datastart nvarchar(20),
    @datastop nvarchar(20)
AS

declare
@val_max real,
@data_min datetime,
@data_max datetime,
@val_data_min real,
@val_data_max real,
@consum real

BEGIN
    SET NOCOUNT ON;

if @id_aparat=1
begin
    select @val_max=max(aparat1),@data_min=min(dataora),@data_max=max(dataora) from table_name where (dataora between convert(datetime,@datastart,101) and convert(datetime,@datastop,101)) and aparat1 is not null

    set @val_data_min=(
    select aparat1 from table_name
    where dataora=@data_min)

    set @val_data_max=(
    select aparat1 from table_name
    where dataora=@data_max)

    if @val_data_max<>@val_max
    begin
    set @consum=@val_max-@val_data_min+@val_data_max
    end
    else
    begin
    set @consum=@val_data_max-@val_data_min
    end

    select @consum
end 

if @id_aparat=2
begin
    select @val_max=max(aparat2),@data_min=min(dataora),@data_max=max(dataora) from table_name where (dataora between convert(datetime,@datastart,101) and convert(datetime,@datastop,101)) and aparat2 is not null

    set @val_data_min=(
    select aparat2 from table_name
    where dataora=@data_min)

    set @val_data_max=(
    select aparat2 from table_name
    where dataora=@data_max)

    if @val_data_max<>@val_max
    begin
    set @consum=@val_max-@val_data_min+@val_data_max
    end
    else
    begin
    set @consum=@val_data_max-@val_data_min
    end

    select @consum
end 

等等,对于名为aparat1,aparat2 ... aparat100的100个列中的每一列。

因此,过程接收整数列标识符和两个日期作为参数,进行一些计算并返回一个值。列标识符标识列并给出列名称(即“aparat”+ @id_aparat)。 我想要的是将计算块放在for语句中,而不是为@id_aparat的每个值复制一百次。可以使用动态SQL来完成这个吗?

编辑:工作代码 问题解决了。对于任何感兴趣的人,这是工作代码:

USE [2013date]
GO
/****** Object:  StoredProcedure [dbo].[GetConsumRealElQRo]    Script Date: 4/18/2013 2:39:19 PM ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO

ALTER PROCEDURE [dbo].[GetConsumRealElQRo] 
    @id_aparat int,
    @datastart nvarchar(20),
    @datastop nvarchar(20)
AS

declare
@val_max real,
@data_min datetime,
@data_max datetime,
@val_data_min real,
@val_data_max real,
@consum real

BEGIN
    SET NOCOUNT ON;

declare 
@aparat as nvarchar(10),
@tabel as nvarchar(50),
@query as nvarchar(1000)

set @aparat = 'aparat' + CONVERT(nvarchar(3),@id_aparat)
set @tabel = 'table_name'

set @query = 'select @val_max=max(' + @aparat + '),@data_min=min(dataora),@data_max=max(dataora) from ' + @tabel + '
    where (dataora between convert(datetime,''' + @datastart + ''',101) and convert(datetime,''' + @datastop + ''',101)) and ' + @aparat + ' is not null'
--select @query
exec sp_executesql @query, N'@val_max real output, @data_min datetime output, @data_max datetime output', @val_max output, @data_min output, @data_max output
--select @val_max
--select @data_min
--select @data_max

set @query = 'set @val_data_min=(select ' + @aparat + ' from ' + @tabel + ' where dataora=''' + Convert(nvarchar(30),@data_min,121) + ''')'
--select @query
exec sp_executesql @query, N'@val_data_min real output',  @val_data_min output
--select @val_data_min

set @query = 'set @val_data_max=(select ' + @aparat + ' from ' + @tabel + ' where dataora=''' + Convert(nvarchar(30),@data_max,121) + ''')'
--select @query
exec sp_executesql @query, N'@val_data_max real output',  @val_data_max output
--select @val_data_max

if @val_data_max<>@val_max
    begin
        set @consum=@val_max-@val_data_min+@val_data_max
    end
else
    begin
        set @consum=@val_data_max-@val_data_min
    end

select @consum

END

2 个答案:

答案 0 :(得分:1)

我没有时间尝试此查询,但您的问题的答案是肯定的。您可以声明一个nvarchar变量@sql1,将此变量设置为查询的字符串,然后执行此变量。所以,再次没有测试这个查询,我们走了。最后的SELECT是能够看到您要执行的查询,exec(@sql1)运行查询。希望这有意义并帮助你!

declare @sql1 nvarchar(4000)
set @sql1 = '
select @val_max=max(aparat' + convert(nvarchar(10),@id_aparat) + '),@data_min=min(dataora),@data_max=max(dataora) from table_name where (dataora between convert(datetime,@datastart,101) and convert(datetime,@datastop,101)) and aparat' +convert(nvarchar(10),@id_aparat)+' is not null

    set @val_data_min=(
    select aparat' + convert(nvarchar(10),@id_aparat) + ' from table_name
    where dataora=@data_min)

    set @val_data_max=(
    select aparat' + convert(nvarchar(10),@id_aparat) + ' from table_name
    where dataora=@data_max)

    if @val_data_max<>@val_max
    begin
        set @consum=@val_max-@val_data_min+@val_data_max
    end
    else
    begin
        set @consum=@val_data_max-@val_data_min
    end

select @consum'

SELECT (@sql1)
exec(@sql1)

答案 1 :(得分:0)

请尝试以下编码....

    ALTER PROCEDURE [dbo].[GetConsumRealElQRo] 
    @id_aparat int,
    @datastart nvarchar(20),
    @datastop nvarchar(20)
AS

declare
@val_max real,
@data_min datetime,
@data_max datetime,
@val_data_min real,
@val_data_max real,
@consum real

BEGIN

    SET NOCOUNT ON;

    Declare @ExecutionString NVARCHAR(500)

    Set @ExecutionString  = '
    Select @val_max=max(aparat'+ Cast( @id_aparat  AS Varchar) +'),@data_min=min(dataora),@data_max=max(dataora) from table_name where (dataora between convert(datetime,@datastart,101) and convert(datetime,@datastop,101)) and aparat1 is not null

        set @val_data_min=(
        select aparat'+ Cast( @id_aparat  AS Varchar) +' from table_name
        where dataora=@data_min)

        set @val_data_max=(
        select aparat'+ Cast( @id_aparat  AS Varchar) +' from table_name
        where dataora=@data_max)

        if @val_data_max<>@val_max
        begin
            set @consum=@val_max-@val_data_min+@val_data_max
        end
        else
        begin
            set @consum=@val_data_max-@val_data_min
        end

        Select @consum
    '

    Exec SP_Executesql @ExecutionString, N'@id_aparat INT', @id_aparat

    SET NOCOUNT OFF;
Go  
相关问题