t-sql, замените Null на последнее значение - содержит Unions - PullRequest
0 голосов
/ 25 апреля 2018

У меня следующий запрос:

declare @s1_data int;
declare @s2_data int;
declare @s3_data int;
declare @s4_data int;
declare @s5_data int;
declare @s6_data int;

select  aa.t_stamp, 
        aa.Stat as S1_Stat, 
        @s2_data as S2_Stat, 
        @s3_data as S3_Stat, 
        @s4_data as S4_Stat, 
        @s5_data as S5_Stat, 
        @s6_data as S6_Stat 
from Line4283_1_rtStat aa 
where t_stamp between '{Root Container.Date Range.startDate}' 
                  and '{Root Container.Date Range.endDate}'
Union
select ab.t_stamp, @s1_data, ab.Stat ,@s3_data, @s4_data, @s5_data, @s6_data 
from Line4283_2_rtStat ab
where t_stamp between '{Root Container.Date Range.startDate}' 
                  and '{Root Container.Date Range.endDate}'
Union
select ac.t_stamp, @s1_data, @s2_data, ac.Stat, @s4_data, @s5_data, @s6_data 
from Line4283_3_rtStat ac
where t_stamp between '{Root Container.Date Range.startDate}'  
                  and '{Root Container.Date Range.endDate}'
Union
select ad.t_stamp, @s1_data, @s2_data, @s3_data, ad.Stat, @s5_data, @s6_data 
from Line4283_4_rtStat ad
where t_stamp between '{Root Container.Date Range.startDate}'  
                  and '{Root Container.Date Range.endDate}'
Union
select ae.t_stamp, @s1_data, @s2_data, @s3_data ,@s4_data, ae.Stat, @s6_data 
from Line4283_5_rtStat ae
where t_stamp between '{Root Container.Date Range.startDate}'  
                  and '{Root Container.Date Range.endDate}'
Union
select af.t_stamp, @s1_data, @s2_data, @s3_data ,@s4_data ,@s5_data, af.Stat 
from Line4283_6_rtStat af
where t_stamp between '{Root Container.Date Range.startDate}'  
                  and '{Root Container.Date Range.endDate}'
union
select '{Root Container.Date Range.endDate}', 0, 0, 0, 0, 0, 0

{Root Container.Date Range.startDate} и {Root Container.Date Range.endDate} - это переменные, которые заполняются во время выполнения.

Этот запрос работает и возвращает что-то подобное, за исключением того, чтоэто результат простого чтения первых двух строк данных:

2018-03-29 11:00:00.000     2       NULL
2018-03-29 12:00:00.000     3       NULL
2018-03-29 13:00:00.000     4       NULL
2018-04-09 15:57:57.270     2       NULL
2018-04-09 16:01:10.193     NULL    1
2018-04-09 16:01:46.430     NULL    7
2018-04-09 16:02:09.547     NULL    1
2018-04-09 16:04:23.710     NULL    3
2018-04-09 16:04:40.850     NULL    1
2018-04-09 16:04:49.907     NULL    3
2018-04-09 16:04:52.920     NULL    1
etc'

Чтобы сделать эту работу, я хотел бы заменить значения NULL последним значением, которое произошло в том же столбце.Я не уверен, как это сделать со всеми этими объединениями, которые необходимы для получения данных в работоспособном формате.

Запрос должен возвращать данные так, как они в настоящее время структурированы, чтобы позволить импортируемому мной инструментуданные в для правильного отображения данных.

Точная версия SQL Server: 13.0.4210.6

В итоге я сделал следующее.Ниже приведена копия процедуры, которую я написал:

ALTER PROCEDURE [dbo].[statusFill] 
-- Add the parameters for the stored procedure here
 @start datetime,
 @end datetime
AS
BEGIN

declare @insertDate datetime;
declare @insertDateSpan datetime;
declare @s1_stat int;
declare @s1_hold int;
declare @s2_stat int;
declare @s2_hold int;
declare @s3_stat int;
declare @s3_hold int;
declare @s4_stat int;
declare @s4_hold int;
declare @s5_stat int;
declare @s5_hold int;
declare @s6_stat int;
declare @s6_hold int;

-- SET NOCOUNT ON added to prevent extra result sets from
-- interfering with SELECT statements.
SET NOCOUNT ON;
SET @insertDate = @start;
IF EXISTS (SELECT * FROM sysobjects WHERE name='status' AND xtype='U')
drop table #status

IF NOT EXISTS (SELECT * FROM sysobjects WHERE name='status' AND xtype='U')
create table #status
( 
t_stamp datetime,
S1_Stat int,
S2_Stat int,
S3_Stat int,
S4_Stat int,
S5_Stat int,
S6_Stat int
)

WHILE @insertDate < @end
BEGIN
select @insertDateSpan = DATEADD(second,5,@insertDate)
if @insertDate = @start
    select @s1_stat = isnull((select top (1) stat from Line4283_1_rtStat     where t_stamp between @insertDate and @insertDateSpan order by t_stamp asc),
    (select top (1) stat from Line4283_1_rtStat where t_stamp <     @insertDate order by t_stamp asc))  
else
    select @s1_stat = isnull((select top (1) stat from Line4283_1_rtStat where t_stamp between @insertDate and @insertDateSpan order by t_stamp asc),@s1_hold)

if @s1_stat is not null
    select @s1_hold = @s1_stat;

-- station #2
if @insertDate = @start
    select @s2_stat = isnull((select top (1) stat from Line4283_2_rtStat     where t_stamp between @insertDate and @insertDateSpan order by t_stamp asc),
    (select top (1) stat from Line4283_2_rtStat where t_stamp <     @insertDate order by t_stamp asc))  
else
    select @s2_stat = isnull((select top (1) stat from Line4283_2_rtStat where t_stamp between @insertDate and @insertDateSpan order by t_stamp asc),@s2_hold)

if @s2_stat is not null
    select @s2_hold = @s2_stat;

-- station #3
if @insertDate = @start
    select @s3_stat = isnull((select top (1) stat from Line4283_3_rtStat     where t_stamp between @insertDate and @insertDateSpan order by t_stamp asc),
    (select top (1) stat from Line4283_3_rtStat where t_stamp <     @insertDate order by t_stamp asc))  
else
    select @s3_stat = isnull((select top (1) stat from Line4283_3_rtStat where t_stamp between @insertDate and @insertDateSpan order by t_stamp asc),@s3_hold)

if  @s3_stat is not null
    select @s3_hold = @s3_stat;

    -- station #4
if @insertDate = @start
    select @s4_stat = isnull((select top (1) stat from Line4283_4_rtStat where t_stamp between @insertDate and @insertDateSpan order by t_stamp asc),
    (select top (1) stat from Line4283_2_rtStat where t_stamp < @insertDate order by t_stamp asc))  
else
    select @s4_stat = isnull((select top (1) stat from Line4283_4_rtStat where t_stamp between @insertDate and @insertDateSpan order by t_stamp asc),@s4_hold)

if @s4_stat is not null
    select @s4_hold = @s4_stat;
-- station #5
if @insertDate = @start
    select @s5_stat = isnull((select top (1) stat from Line4283_5_rtStat     where t_stamp between @insertDate and @insertDateSpan order by t_stamp asc),
    (select top (1) stat from Line4283_5_rtStat where t_stamp <     @insertDate order by t_stamp asc))  
else
    select @s5_stat = isnull((select top (1) stat from Line4283_5_rtStat where t_stamp between @insertDate and @insertDateSpan order by t_stamp asc),@s5_hold)

if @s5_stat is not null
    select @s5_hold = @s5_stat;

-- station #6
if @insertDate = @start
    select @s6_stat = isnull((select top (1) stat from Line4283_6_rtStat     where t_stamp between @insertDate and @insertDateSpan order by t_stamp asc),
    (select top (1) stat from Line4283_6_rtStat where t_stamp <     @insertDate order by t_stamp asc))  
else
    select @s6_stat = isnull((select top (1) stat from Line4283_6_rtStat where t_stamp between @insertDate and @insertDateSpan order by t_stamp asc),@s6_hold)

if @s6_stat is not null
    select @s6_hold = @s6_stat;






insert into #status (t_stamp,S1_Stat,S2_Stat,S3_Stat,S4_Stat,S5_Stat,S6_Stat)
select @insertDate,@s1_stat,@s2_stat,@s3_stat,@s4_stat,@s5_stat,@s6_stat
select @insertDate =DATEADD(second,5,@insertDate)
END;


select t_stamp,S1_Stat,S2_Stat,S3_Stat,S4_Stat,S5_Stat,S6_Stat  from #status
drop table #status
END

Это было немного по-другому, но на самом деле оно выполняется менее чем за секунду для типичного выполнения.Это позволяет мне создать 5-секундные окна и либо заполнить их данными, либо вставить последнее известное значение.

...