Хранимая процедура SQL Server повторяет операции с временной таблицей - PullRequest
0 голосов
/ 18 сентября 2018

У меня есть хранимая процедура в SQL Server, которая генерирует много отчетов, все отчеты имеют общий столбец и столбец вычисления в процентах. Таким образом, последняя строка временной таблицы является итоговым столбцом. Ниже приведен мой код.

declare @Yr1Tot int, @Yr2Tot int
create table #SrcCnt(id int identity(1,1), Src varchar(100), Yr1Cnt money, Yr1Per varchar(20), Yr2Cnt money, Yr2Per varchar(20))

-- Report 1 generation
insert into #SrcCnt(Src, Yr1Cnt,Yr2Cnt)
select 'Rep1-1', 10 , 20 union
select 'Rep1-2', 1 , 2 union
select 'Rep1-3', 15 , 25 union
select 'Rep1-4', 8 , 87 union
select 'Rep1-5', 4 , 5 union
select 'Rep1-6', 7 , 9 union
select 'Rep1-7', 11 , 30 

-- Following block is repeated for all reports
insert into #SrcCnt(Src, Yr1Cnt,Yr2Cnt)
select 'Total', sum(Yr1Cnt), sum(Yr2Cnt) from #SrcCnt

select @Yr1Tot = Yr1Cnt, @Yr2Tot = Yr2Cnt from #SrcCnt where Src = 'Total'

update #SrcCnt set Yr1Per = (Yr1Cnt * 100)/@Yr1Tot 
update #SrcCnt set Yr2Per = (Yr2Cnt * 100)/@Yr2Tot

update #SrcCnt set Yr1Per = case when Yr1Per = '0' then null else Yr1Per + '%' end 
update #SrcCnt set Yr2Per = case when Yr2Per = '0' then null else Yr2Per + '%' end 

select * from #SrcCnt order by id
 -- End of repetative code



-- Report 2 generation

delete from #SrcCnt

insert into #SrcCnt(Src, Yr1Cnt,Yr2Cnt)
select 'Rep2-1', 10 , 20 union
select 'Rep2-2', 1 , 2 union
select 'Rep2-3', 15 , 25 union
select 'Rep2-4', 8 , 87 union
select 'Rep2-5', 4 , 5 union
select 'Rep2-6', 7 , 9 union
select 'Rep2-7', 11 , 30 


insert into #SrcCnt(Src, Yr1Cnt,Yr2Cnt)
select 'Total', sum(Yr1Cnt), sum(Yr2Cnt) from #SrcCnt


select @Yr1Tot = Yr1Cnt, @Yr2Tot = Yr2Cnt from #SrcCnt where Src = 'Total'

update #SrcCnt set Yr1Per = (Yr1Cnt * 100)/@Yr1Tot 
update #SrcCnt set Yr2Per = (Yr2Cnt * 100)/@Yr2Tot

update #SrcCnt set Yr1Per = case when Yr1Per = '0' then null else Yr1Per + '%' end 
update #SrcCnt set Yr2Per = case when Yr2Per = '0' then null else Yr2Per + '%' end 

select * from #SrcCnt order by id


-- Report 3 generation

delete from #SrcCnt

insert into #SrcCnt(Src, Yr1Cnt,Yr2Cnt)
select 'Rep3-1', 10 , 20 union
select 'Rep3-2', 1 , 2 union
select 'Rep3-3', 15 , 25 union
select 'Rep3-4', 8 , 87 union
select 'Rep3-5', 4 , 5 union
select 'Rep3-6', 7 , 9 union
select 'Rep3-7', 11 , 30 


insert into #SrcCnt(Src, Yr1Cnt,Yr2Cnt)
select 'Total', sum(Yr1Cnt), sum(Yr2Cnt) from #SrcCnt


select @Yr1Tot = Yr1Cnt, @Yr2Tot = Yr2Cnt from #SrcCnt where Src = 'Total'

update #SrcCnt set Yr1Per = (Yr1Cnt * 100)/@Yr1Tot 
update #SrcCnt set Yr2Per = (Yr2Cnt * 100)/@Yr2Tot

update #SrcCnt set Yr1Per = case when Yr1Per = '0' then null else Yr1Per + '%' end 
update #SrcCnt set Yr2Per = case when Yr2Per = '0' then null else Yr2Per + '%' end 

select * from #SrcCnt order by id

Итак, теперь в моей хранимой процедуре есть как минимум 30 отчетов, все они должны быть сгенерированы при вызове этого SP, что означает, что мне нужно несколько раз повторить код полной генерации и процентной генерации, как показано в коде выше. Есть ли лучший подход, чем создание UserDefined DataTable / копирование и вставка его несколько раз.

1 Ответ

0 голосов
/ 18 сентября 2018

Я думаю, что лучший способ сделать это - обернуть вычисление процентного кода в пользовательскую функцию (udf), которая возвращает таблицу.Передайте переменную типа таблицы в udf, выполните вычисления в udf и вызовите udf, чтобы получить набор результатов в виде строк данных таблицы.Однако для передачи таблицы в udf необходимо создать тип таблицы, определяемый пользователем.

Вот примеры кодов:

/ * Create User Defined Table Type */
CREATE TYPE x2_SrcCntTableType AS TABLE (
   id int identity(1,1)
   ,Src varchar(100)
   , Yr1Cnt money
   , Yr1Per varchar(20)
   , Yr2Cnt money
   , Yr2Per varchar(20))
GO

/* Create User Defined Table-Valued Function */
        CREATE FUNCTION x2_getSrcCntPercentage
    (
        @srcCntOrig x2_SrcCntTableType READONLY -- this table should always readonly

    )
    RETURNS 
    @SrcCnt TABLE 
    (
        -- Add the column definitions for the TABLE variable here
          id int identity(1,1)
        , Src varchar(100)
        , Yr1Cnt money
        , Yr1Per varchar(20)
        , Yr2Cnt money
        , Yr2Per varchar(20)
    )
    AS
    BEGIN
        -- Fill the table variable with the rows for your result set
        -- copy data from @srcCntOrig to @SrcCnt table
        -- because srcCntOrig is readonly, so do the udates on table SrcCnt 

         insert into  @SrcCnt(Src, Yr1Cnt,Yr2Cnt)
         SELECT   Src, Yr1Cnt,Yr2Cnt FROM @srcCntOrig

         insert into @SrcCnt(Src, Yr1Cnt,Yr2Cnt)
         select 'Total', sum(Yr1Cnt), sum(Yr2Cnt) from @SrcCnt



        declare @Yr1Tot int, @Yr2Tot int

        select @Yr1Tot = Yr1Cnt, @Yr2Tot = Yr2Cnt from @SrcCnt where Src = 'Total'

        update @SrcCnt set Yr1Per = (Yr1Cnt * 100)/@Yr1Tot 
        update @SrcCnt set Yr2Per = (Yr2Cnt * 100)/@Yr2Tot

        update @SrcCnt set Yr1Per = case when Yr1Per = '0' then null else Yr1Per + '%' end 
        update @SrcCnt set Yr2Per = case when Yr2Per = '0' then null else Yr2Per + '%' end 

        -- select * from #SrcCnt order by id

        RETURN 
    END
GO

И затем вы можете вызвать udf из запроса / хранимой процедуры:

    declare @SrcCnt x2_SrcCntTableType

    INSERT INTO @SrcCnt(Src,Yr1Cnt,Yr2Cnt) VALUES ('0 - 5 Years',143,43)
    INSERT INTO @SrcCnt(Src,Yr1Cnt,Yr2Cnt) VALUES ('6 - 10 Years',28,17)
    INSERT INTO @SrcCnt(Src,Yr1Cnt,Yr2Cnt) VALUES ('11 - 15 Years',9,5)
    INSERT INTO @SrcCnt(Src,Yr1Cnt,Yr2Cnt) VALUES ('16 - 20 Years',7,2)
    INSERT INTO @SrcCnt(Src,Yr1Cnt,Yr2Cnt) VALUES ('21 - 30 Years',11,3)
    INSERT INTO @SrcCnt(Src,Yr1Cnt,Yr2Cnt) VALUES ('> 30  Years',91,55)

    SELECT * from dbo.x2_getSrcCntPercentage(@SrcCnt)

Результат:

id  Src             Yr1Cnt   Yr1Per Yr2Cnt  Yr2Per
---------------------------------------------------
1   0 - 5 Years     143,00   49.48%  43,00   34.40%
2   6 - 10 Years     28,00    9.69%  17,00   13.60%
3   11 - 15 Years     9,00    3.11%   5,00    4.00%
4   16 - 20 Years     7,00    2.42%   2,00    1.60%
5   21 - 30 Years    11,00    3.81%   3,00    2.40%
6   > 30  Years      91,00   31.49%  55,00   44.00%
7   Total           289,00  100.00% 125,00  100.00%

(обновлено) ОК.Есть еще один вариант без использования UDF.Однако вам необходимо иметь общее количество Yr1Cnt и Yr2Cnt, прежде чем делать вставки в таблицу @SrcCnt.Хитрость в том, чтобы использовать компьютерную колонку.

Вот частичный код вашей хранимой процедуры:

declare @SrcCnt TABLE 
    (
        -- Add the column definitions for the TABLE variable here
          id int identity(1,1)
        , Src varchar(100)
        , Yr1Cnt money
        , Yr1Per AS Cast(Cast((Yr1Cnt/TotYr1Cnt)*100 as decimal(18,2)) as varchar(10)) + ' %' -- COMPUTED COLUMN
        , Yr2Cnt money
        , Yr2Per AS Cast(Cast((Yr2Cnt/TotYr2Cnt)*100 as decimal(18,2)) as varchar(10)) + ' %' -- COMPUTED COLUMN
        , TotYr1Cnt money
        , TotYr2Cnt money
    )

    declare @TotYr1Cnt money = 289 -- maybe calculated elsewhere but prior to inserting data to @SrcCnt
    declare @TotYr2Cnt money = 125

    INSERT INTO @SrcCnt(Src,Yr1Cnt,Yr2Cnt,TotYr1Cnt,TotYr2Cnt) VALUES ('0 - 5 Years',143,43,@TotYr1Cnt,@TotYr2Cnt)
    INSERT INTO @SrcCnt(Src,Yr1Cnt,Yr2Cnt,TotYr1Cnt,TotYr2Cnt) VALUES ('6 - 10 Years',28,17,@TotYr1Cnt,@TotYr2Cnt)
    INSERT INTO @SrcCnt(Src,Yr1Cnt,Yr2Cnt,TotYr1Cnt,TotYr2Cnt) VALUES ('11 - 15 Years',9,5,@TotYr1Cnt,@TotYr2Cnt)
    INSERT INTO @SrcCnt(Src,Yr1Cnt,Yr2Cnt,TotYr1Cnt,TotYr2Cnt) VALUES ('16 - 20 Years',7,2,@TotYr1Cnt,@TotYr2Cnt)
    INSERT INTO @SrcCnt(Src,Yr1Cnt,Yr2Cnt,TotYr1Cnt,TotYr2Cnt) VALUES ('21 - 30 Years',11,3,@TotYr1Cnt,@TotYr2Cnt)
    INSERT INTO @SrcCnt(Src,Yr1Cnt,Yr2Cnt,TotYr1Cnt,TotYr2Cnt) VALUES ('> 30  Years',91,55,@TotYr1Cnt,@TotYr2Cnt)

    INSERT INTO @SrcCnt(Src,Yr1Cnt,Yr2Cnt,TotYr1Cnt,TotYr2Cnt) VALUES ('Total',@TotYr1Cnt,@TotYr2Cnt,@TotYr1Cnt,@TotYr2Cnt)

     SELECT * FROM @SrcCnt
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...