简体   繁体   English

在oracle中比较行值

[英]Comparing row values in oracle

I have Table1 with three columns: 我有Table1有三列:

 Key | Date   | Price
----------------------
 1   | 26-May | 2
 1   | 25-May | 2
 1   | 24-May | 2
 1   | 23 May | 3
 1   | 22 May | 4
 2   | 26-May | 2
 2   | 25-May | 2
 2   | 24-May | 2
 2   | 23 May | 3
 2   | 22 May | 4

I want to select the row where value 2 was last updated (24-May) . 我想选择值2最近一次更新(24-May) The Date was sorted using RANK function. 日期使用RANK函数排序。 I am not able to get the desired results. 我无法获得预期的结果。 Any help will be appreciated. 任何帮助将不胜感激。

SELECT *
  FROM (SELECT key, DATE, price,
               RANK() over (partition BY key order by DATE DESC) AS r2 
          FROM Table1 ORDER BY DATE DESC) temp;

Another way of looking at the problem is that you want to find the most recent record with a price different from the last price. 解决问题的另一种方法是,您要查找价格与最新价格不同的最新记录。 Then you want the next record. 然后,您需要下一条记录。

with lastprice as (
      select t.*
      from (select t.*
            from table1 t
            order by date desc
           ) t
      where rownum = 1
     )
select t.*
from (select t.*
      from table1 t
      where date > (select max(date)
                    from table1 t2
                    where t2.price <> (select price from lastprice)
                   )
     order by date asc
    ) t
where rownum = 1;

This query looks complicated. 该查询看起来很复杂。 But, it is structured so it can take advantage of indexes on table1(date) . 但是,它是结构化的,因此可以利用table1(date)上的索引。 The subqueries are necessary in Oracle pre-12. 子查询在Oracle 12之前的版本中是必需的。 In the most recent version, you can use fetch first 1 row only . 在最新版本中,您只能使用fetch first 1 row only

EDIT: 编辑:

Another solution is to use lag() and find the most recent time when the value changed: 另一种解决方案是使用lag()并在值更改时查找最近的时间:

select t1.*
from (select t1.*
      from (select t1.*,
                   lag(price) over (order by date) as prev_price
            from table1 t1
           ) t1
      where prev_price is null or prev_price <> price
      order by date desc
     ) t1
where rownum = 1;

Under many circumstances, I would expect the first version to have better performance, because the only heavy work is done in the innermost subquery to get the max(date) . 在许多情况下,我希望第一个版本具有更好的性能,因为只有最繁重的工作在最里面的子查询中才能获得max(date) This verson has to calculate the lag() as well as doing the order by . 这个人必须计算lag()并按进行order by However, if performance is an issue, you should test on your data in your environment. 但是,如果性能成为问题,则应在环境中测试数据。

EDIT II: 编辑二:

My best guess is that you want this per key . 我最好的猜测是每个key都需要这个。 Your original question says nothing about key , but: 您最初的问题没有说明key ,但是:

select t1.*
from (select t1.*,
             row_number() over (partition by key order by date desc) as seqnum
      from (select t1.*,
                   lag(price) over (partition by key order by date) as prev_price
            from table1 t1
           ) t1
      where prev_price is null or prev_price <> price
      order by date desc
     ) t1
where seqnum = 1;

You can try this:- 您可以尝试以下方法:

SELECT Date FROM Table1
WHERE Price = 2
AND PrimaryKey = (SELECT MAX(PrimaryKey) FROM Table1
                  WHERE Price = 2)

This is very similar to the second option by Gordon Linoff but introduces a second windowed function row_number() to locate the most recent row that changed the price. 这与Gordon Linoff的第二个选项非常相似,但是引入了第二个窗口函数row_number()来查找更改价格的最新行。 This will work for all or a range of keys. 这将适用于所有或一系列键。

select
* 
from (
      select
            *
            , row_number() over(partition by Key order by [date] DESC) rn
      from (
            select
                *
                , NVL(lag(Price) over(partition by Key order by [date] DESC),0) prevPrice
            from table1
            where Key IN (1,2,3,4,5) -- as an example
           )
      where Price <> prevPrice
     )
where rn = 1

apologies but I haven't been able to test this at all. 抱歉,我根本无法测试。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM