【问题标题】:Oracle - Finding the NEXT largest numberOracle - 寻找下一个最大的数字
【发布时间】:2017-03-24 18:57:12
【问题描述】:

假设我有一份日期和价格清单:

20170322    109.89
20170321    107.02
20170320    109.25
20170317    108.44
20170316    108.53
20170315    107.94
20170314    106.83
20170313    110.02
20170310    107.31
20170309    107.54
20170308    107.67
20170307    108.98

我需要的是,从最近的日期:20170322 (109.89),第一个日期/价格值高于原始值,即 20170313 (110.02)。请注意,这些是按日期的 DESC 顺序排列的

一整天都在这。

【问题讨论】:

  • 请发布您的预期输出
  • 所以:“原始”值(价格)为 108.98,价格上涨的第一个日期是 20170313,当时价格为 110.02。我们可能必须假设 20170307 是整个表中的第一个日期(否则它有什么特别之处?)完全不清楚的是你的意思是 从最近的日期 - 你不是说(并通过示例显示)您从最早的日期开始,并且您想要价格高于原始日期的第一个日期? 最近的日期在这一切中扮演什么角色?另外,如果价格从未高于原价,您想看看什么?
  • 你有什么版本的Oracle?运行SELECT * FROM V$VERSION 找出答案。在 Oracle 12.1 及以上版本中,有一个非常简单的解决方案,MATCH_RECOGNIZE

标签: oracle sorting next highest


【解决方案1】:

假设列名为 DT 和 PRICE,并假设您监控的价格只有一个“事物”(否则您需要一个 GROUP BY 子句):

select min(dt) as dt, min(price) keep (dense_rank first order by dt) as price
from   your_table
where  price > ( select min(price) keep (dense_rank first order by dt)
                 from   your_table
               )

https://docs.oracle.com/cd/B19306_01/server.102/b14200/functions056.htm

【讨论】:

  • 这很好。不太确定我是否了解 DENSE_RANK 的工作原理......但我很感激这个快速帮助!
  • @LandonStatis - 这就是我添加 Oracle 文档链接的原因,您可以在其中找到解释、语法和示例。如果您不习惯阅读 Oracle 文档,请养成阅读的习惯;一开始有点吓人,但它有巨大的好处。
【解决方案2】:

使用 MATCH_RECOGNIZE 子句的解决方案(需要 Oracle 12 及更高版本)。

我在 WITH 子句中创建了测试数据。这不是解决方案的一部分; SQL 查询在 WITH 子句之后开始,位于 SELECT TICKER, ....

PATTERN 中勉强匹配中的问号会使 JDBC 驱动程序跳闸,因此无法从 SQL Developer 运行此查询;它需要在 SQL*Plus 或类似的前端中运行。 (解决方法是将b*? 更改为b* 并添加到DEFINE 子句:b as b.price <= a.price。)

为了说明MATCH_RECOGNIZE 的更多灵活性,我假设可能有几个“代码”,每个都有其开始日期(价格最早的日期),并且查询查找价格高于原始的,每行代码。

with
     test_data ( ticker, dt, price ) as (
       select 'XYZ', to_date('20170322', 'yyyymmdd'), 109.89 from dual union all
       select 'XYZ', to_date('20170321', 'yyyymmdd'), 107.02 from dual union all
       select 'XYZ', to_date('20170320', 'yyyymmdd'), 109.25 from dual union all
       select 'XYZ', to_date('20170317', 'yyyymmdd'), 108.44 from dual union all
       select 'XYZ', to_date('20170316', 'yyyymmdd'), 108.53 from dual union all
       select 'XYZ', to_date('20170315', 'yyyymmdd'), 107.94 from dual union all
       select 'XYZ', to_date('20170314', 'yyyymmdd'), 106.83 from dual union all
       select 'XYZ', to_date('20170313', 'yyyymmdd'), 110.02 from dual union all
       select 'XYZ', to_date('20170310', 'yyyymmdd'), 107.31 from dual union all
       select 'XYZ', to_date('20170309', 'yyyymmdd'), 107.54 from dual union all
       select 'XYZ', to_date('20170308', 'yyyymmdd'), 107.67 from dual union all
       select 'XYZ', to_date('20170307', 'yyyymmdd'), 108.98 from dual
     )
select ticker, dt, price
from   test_data
match_recognize (
  partition by ticker
  order     by dt
  measures  c.dt as dt, c.price as price
  one row per match
  pattern   ( ^ a b*? c )
  define    c as c.price > a.price
)
;

TICKER  DT            PRICE
------  ----------  -------
XYZ     2017-03-13   110.02

1 row selected.

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-02-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多