我需要查询以获取给定表的输出

时间:2018-08-24 13:22:17

标签: sql oracle

表位置如下。

CREATE TABLE position (
tran_Date date,
clientid varchar(255),
stock varchar(255),
quantity number
);

insert into position values ('23-AUG-2018','Client1','Infosys',100);
insert into position values ('23-AUG-2018','Client1','Wipro',200);
insert into position values ('23-AUG-2018','Client1','TechM',150);
insert into position values ('23-AUG-2018','Client2','IBM',100);
insert into position values ('24-AUG-2018','Client1','Infosys',150);
insert into position values ('24-AUG-2018','Client1','Wipro',150);
insert into position values ('24-AUG-2018','Client2','IBM',100);

我需要查询以从位置表中获取数据,格式如下。答案应该是一个查询。

ClientID, 
Stock, 
ChangeInQty(a calculative bucket which will hold the diff of qty between 2 dates),
classification(a calculative bucket on changeinqty. 
    IF changeinqty in '-'(negative) 'shares taken down'
    if changeinqty in '+'(positive) 'shares taken up'
    if changeinqty in '0'(no change) 'shares remain same'
    if changeinqty is indeterminable 'shares position removed')

我的方法是这样。

Select clientid,stock,changeinqty, 
case 
when x.changeinqty >0 then 'Taken Up'
when x.changeinqty <0 then 'Taken Down'
when x.changeinqty =0 then 'Same'
when x.changeinqty is null then 'Removed'
end as classification
From (select a.clientid,a.stock,a.quantity-b.quantity as changeinqty from
(Select tran_date,clientid,stock,quantity from position where tran_date='23-Aug-2018')  a left join
(Select tran_date,clientid,stock,quantity from position where tran_date='24-Aug-2018')  b
on a.clientid=b.clientid and a.stock=b.stock) x;

4 个答案:

答案 0 :(得分:2)

这是另一种查找方法

select clientid,
stock, 
quantity,
a.change_stock,
case when a.change_stock < 0 THEN  'shares taken down' 
when a.change_stock > 0 THEN  'shares taken up'
when a.change_stock = 0 THEN  'shares remain same' end classification from (
Select clientid,stock, quantity,  lead(quantity,1,0) over ( partition by clientid,stock order by tran_Date asc) - quantity change_stock 
from position ) a
where a.quantity + a.change_stock <> 0
union all
select clientid, -- query to take non-duplicate row
stock, 
quantity,null,'shares position removed' from (select clientid,
stock, 
quantity , count(*) over (partition by clientid,stock) cnt from position )a where a.cnt=1;

这里是组合查询,可处理重复项和非重复项,而无需全部合并

select clientid,
stock, 
quantity,
case when a.cnt=1 THEN NULL ELSE a.change_stock END change_stock,
case when a.change_stock < 0 and a.cnt > 1 THEN  'shares taken down' 
when a.change_stock > 0 and a.cnt > 1 THEN  'shares taken up'
when a.change_stock = 0 and a.cnt > 1 THEN  'shares remain same' 
when a.cnt=1 THEN 'shares position removed' end classification from (
Select clientid,stock, quantity,  lead(quantity,1,0) over ( partition by clientid,stock order by tran_Date asc) - quantity change_stock ,count(*) over (partition by clientid,stock) cnt
from position ) a
where a.quantity + a.change_stock <> 0 or cnt=1;

答案 1 :(得分:1)

您的查询看起来还可以,但我可以将其简化为:

Select p1.clientid, p1.stock, (p2.quantity - p1.quantity) as changeinqty, 
       (case when p2.quantity is null then 'Removed'
             when p2.quantity > p1.quantity then 'Taken Up'
             when p2.quantity < p1.quantity then 'Taken Down'
             when p2.quantity = p1.quantity then 'Same'
        end) as classification
From position p1 left join
     position p2
     on p1.client_id = p2.client_id and
        p1.stock = p2.stock and
        p2.tran_date = date '2018-08-24'
where p1.tran_date = date '2018-08-23;

注意:

  • 第一个日期的条件在where子句中,因此只有这些位置。
  • 第二个日期的条件在on子句中,因此包括从第一个日期起的所有行,甚至包括那些缺少的行。
  • 我认为您代码的逻辑是向后的。这更加透明。
  • Oracle支持date关键字,因此您可以将ISO / ANSI标准格式用于日期。

答案 2 :(得分:1)

我会把它浓缩成这样:

select day1.clientid
     , day1.stock
     , day1.quantity - day2.quantity as changeinqty
     , case sign(day1.quantity - day2.quantity)
           when 1 then 'Up'
           when -1 then 'Down'
           when 0 then 'Unchanged'
           else 'Removed'
       end as classification
from   demo_position day1
       left join demo_position day2
            on  day2.clientid = day1.clientid
            and day2.stock = day1.stock
            and day2.tran_date = day1.tran_date +1
where  day1.tran_date = date '2018-08-23';

我猜测(也许是错误地)报告将一天与第二天进行比较,所以我用day1.tran_date +1替换了后来的硬编码日期。

(就像看到戈登的答案一样。正如他在答案中提到的那样,看来day1.quantity - day2.quantity实际上应该是day2.quantity - day1.quantity才能与Up / Down / Unchanged标签匹配。在我使用标签时更改了标签,因为takedowntakeup似乎并不是您的意思。)

答案 3 :(得分:1)

您在脚本中包含了硬编码日期。这适用于您的示例数据,但是如果日期中有任何间隔,将失败。以下脚本扫描先前的位置,并将当前行的位置与最后一个位置进行比较。这适用于任何数据和任何日期:

select *, (p.quantity - prevP.quantity) as change
from dbo.position p
left outer join dbo.position prevP
on p.clientid = prevP.clientid
    and p.stock = prevP.stock
    and prevP.tran_Date = (select max(allPrevP.tran_Date)
                            from dbo.position allPrevP
                            where allPrevP.clientid = prevP.clientid
                                and allPrevP.stock = p.stock
                                and allPrevP.tran_Date < p.tran_Date
                            group by allPrevP.clientid, allPrevP.stock)
order by p.clientid, p.stock, p.tran_Date