TOP 1或LIMIT 1不在相关子查询中工作 - SPS 11

时间:2017-02-24 15:44:05

标签: sql hana

我正在尝试使用查询来填充产品的价格,其中零件的价格为前一记录的非零值。我试着编写一个简单的相关子查询,但它不起作用。

var_1 = select * from "XYZ"."PRD_TEST" where price <> 0 order by period desc;

var_out = select a.product,a.period, ( select price from :var_1 b where a.product = b.product and a.period > b.period and b.period <> 0 limit 1 ) as price from "XYZ"."PRD_TEST" a;

PRODUCT PERIOD PRICE
A 1 100
A 2 0 - to be filled with 100
A 3 0 - to be filled with 100
A 4 5
A 5 0 - to be filled with 5

我尝试用标量函数替换子查询,但它不将表作为参数。

我尝试使用Left outer join和Row_number来实现输出,但它太昂贵并且运行了很长时间。

我正在寻找一个最好的选项来获取子查询中的1条记录,就像TOP 1一样。

1 个答案:

答案 0 :(得分:1)

您可以使用这样的标量子查询(不幸的是,选择...限制1在HANA中不被视为标量):

    Do begin

var_1 = select * from (( Select 'A' product, '1' period, '100' price from sys.dummy )
Union ( Select 'A' product, '2' period, '0' price from sys.dummy )
Union ( Select 'A' product, '3' period, '0' price from sys.dummy )
Union ( Select 'A' product, '4' period, '5' price from sys.dummy )
Union ( Select 'A' product, '5' period, '0' price from sys.dummy )) order by period desc;

var_out = ( select a.product,
             a.period, 
            ( select max(price) 
              from :var_1 b 
              where a.product = b.product 
              and a.period > b.period 
              and b.period <> 0 
              and b.period = ( select max(period) from :var_1 c 
                               where a.product = c.product
                                 AND a.period > c.period
                                 and c.period <> 0
                                 and c.price <> 0
              )) as price 
              from :var_1 a where price = '0' )
union (select product, period, price from :var_1 where price <> '0' );

select * from :var_out order by product, period;
end

在sps12上测试

评论后添加。 你为什么不试试?这很简单。 因为我很好奇,所以我在我的HCP试验实例上试过它,对于milion行需要大约1秒。我包含了一个ifnull,以避免在早期阶段没有价格的情况下使用空值的行。

以下是编码:

drop table var_1;
create column table var_1 as 
(
    select 
      cast ( 'Prod' || prd.GENERATED_PERIOD_START as nvarchar(20) ) product, 
      cast ( per.GENERATED_PERIOD_START as decimal(2)) period,
      cast ( case when rand() < '0.5' then rand() * '100' else '0' end 
             as decimal(5,2)) as price -- ~50% of price is 0
      from series_generate_integer(1,0,1000000/13) as prd,  --~1Mio records
           series_generate_integer(1,0,13) as per --12 periods + period 0 
);
merge delta of var_1;
select * from var_1
 order by product, period 
 limit 100;
do begin sequential execution -- don't let parallel execution influence the runtime-measurement
declare start_timestamp timestamp;
start_timestamp = current_timestamp;
var_out = ( select a.product,
             a.period, 
            ifnull ((select max(price) 
              from var_1 b 
              where a.product = b.product 
              and a.period > b.period 
              and b.period <> 0 
              and b.period = ( select max(period) from var_1 c 
                               where a.product = c.product
                                 AND a.period > c.period
                                 and c.period <> 0
                                 and c.price <> 0
              )),'0.0') as price 
              from var_1 a where price = '0' )
union (select product, period, price from var_1 where price <> '0' );

select nano100_between(:start_timestamp, (select current_timestamp from dummy) )/10000 as runtime_millisec from dummy;

select * from :var_out
 order by product, period 
 limit 100;
end