比较oracle中的行值

Posted

技术标签:

【中文标题】比较oracle中的行值【英文标题】:Comparing row values in oracle 【发布时间】:2015-09-29 09:49:38 【问题描述】:

我有 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

我想选择上次更新值 2 的行 (24-May)。日期使用RANK 函数排序。 我无法获得预期的结果。任何帮助将不胜感激。

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

【问题讨论】:

你试过的查询在哪里? SELECT * FROM (SELECT primary_key, DATE, price, RANK() over (partition BY primary_key order by DATE DESC) AS r2 FROM Table1 ORDER BY DATE DESC ) temp 我不明白,你想返回 pk = 3 的行而不返回其他行?怎么会? 我提到我想检索上次插入值 2 的行,然后它没有改变(我不想检索其他行,因为我不想要它们) 【参考方案1】:

查看问题的另一种方法是,您希望找到价格与上次价格不同的最新记录。然后你想要下一条记录。

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;

这个查询看起来很复杂。但是,它是结构化的,因此它可以利用table1(date) 上的索引。在 Oracle pre-12 中子查询是必需的。在最新版本中,您可以使用fetch first 1 row only

编辑:

另一种解决方案是使用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;

在许多情况下,我希望第一个版本有更好的性能,因为唯一繁重的工作是在最里面的子查询中完成以获得max(date)。这个版本必须计算lag() 以及做order by。但是,如果性能是一个问题,您应该在您的环境中测试您的数据。

编辑二:

我最好的猜测是你想要这个每个key。你原来的问题没有提到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;

【讨论】:

感谢 Gordon 的回复。如果我在 where 子句中指定单个键但多个键失败,则效果很好。我已更新问题。您已正确理解问题。 我不明白key 在您修改后的问题中所扮演的角色。 当我运行你提出的sql时,修改后的键会干扰结果。如果所有键的值相同,那么它工作正常。【参考方案2】:

你可以试试这个:-

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

【讨论】:

这是一个示例...我无法在 sql 中硬编码。还有其他行的值可能不同【参考方案3】:

这与 Gordon Linoff 的第二个选项非常相似,但引入了第二个窗口函数 row_number() 来定位最近更改价格的行。这将适用于所有或一系列键。

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

抱歉,我根本无法对此进行测试。

【讨论】:

以上是关于比较oracle中的行值的主要内容,如果未能解决你的问题,请参考以下文章

比较熊猫数据框中的行值

比较多行的行值 (R)

如何从 ASP.NET C# 中的 SqlDataSource 获取特定的行值?

在插入触发器之后修改一列并更新 Oracle 中新插入的行值

在oracle中将行值添加到列

Excel宏比较两个工作表中的两列并插入行值