【问题标题】:Choose Unique Row and Previous Value Within Oracle's SQL在 Oracle 的 SQL 中选择唯一行和上一个值
【发布时间】:2020-11-27 05:56:01
【问题描述】:

我使用的表有时会重复相同的数据,我想查询它以获取最新的值和之前的值。表格是这样的:

+-------------+----------------+------+-------+
| Item Number | Effective Date | Cost | Price |
+-------------+----------------+------+-------+
|      1      |   01/01/2020   | 8.00 | 11.00 |
|      1      |   01/01/2020   | 8.00 | 10.50 |
|      2      |   09/22/2020   | 6.25 |  6.50 |
|      1      |   01/01/2020   | 8.00 | 10.50 |
|      1      |   05/07/2019   | 7.00 | 10.50 |
|      1      |   03/12/2018   | 6.00 | 10.50 |
|      2      |   03/12/2018   | 6.00 |  6.50 |
|      2      |   03/12/2018   | 6.00 |  6.50 |
|      1      |   01/01/2020   | 7.00 | 10.50 |
|      1      |   08/01/2016   | 5.25 | 10.50 |
+-------------+----------------+------+-------+

我试图让查询结果列出最近成本的日期,并且日期和成本是它之前的日期,并忽略所有重复的数据,如下所示:

+-------------+---------------+---------------+--------------+--------------+
| Item Number | Previous Date | Previous Cost | Current Date | Current Cost |
+-------------+---------------+---------------+--------------+--------------+
|      1      |   05/07/2019  |     7.00      |  01/01/2020  |     8.00     |
|      2      |   03/12/2018  |     6.00      |  09/22/2020  |     6.50     |
+-------------+---------------+---------------+--------------+--------------+

我一直在为延迟和分区而苦苦挣扎,但我仍然得到这样的重复:

+-------------+---------------+---------------+--------------+--------------+
| Item Number | Previous Date | Previous Cost | Current Date | Current Cost |
+-------------+---------------+---------------+--------------+--------------+
|      1      |   01/20/2020  |     8.00      |  01/01/2020  |     8.00     |
+-------------+---------------+---------------+--------------+--------------+

感谢您的任何想法!

【问题讨论】:

  • Effective Date 有时间组件吗?如果不是,您怎么知道 4 条不同的 01/01/2020 记录中的哪一条是第 1 项的最新记录?
  • 请查看How to Ask。将其作为问题模板可以极大地提高您获得满意答案的机会。在这种情况下,实际表描述(如果可能,则为 ddl)和当前/最佳查询。据了解,它不起作用。此外,对于您的示例数据,您如何确定 Current_Date 和 Cost(假设 current_date 对应于您描述中的“最新”)。 item_number 1 和日期 2020-01-01 有 5 行,具有不同的演员表值。
  • 正确。有多个行,其中项目、日期和成本相同。那就是问题所在。对于我需要的结果,它们都被认为是相等的,我需要最近日期之前的记录是以前的。
  • 所以,就像我在示例结果中输入的那样:01/01/20 是项目 1 的最新成本 8.00。在那之前?它是 7.00,于 2019 年 5 月 7 日生效。没有当前或最佳查询,只有一个温暖的失败桶。
  • 但是数据表明 01/01/2020 成本 8.00 比 01/01/2020 成本 7.00 更新?

标签: sql oracle duplicates


【解决方案1】:

我想您需要在按日期列降序排列时查看每个项目编号的最后两条记录。我准备了这个分组和排序,并在下面的查询中使用DISTINCT 消除了重复的行,但我们不知道 Belayer 发现的共同日期的最新成本。我只是将最大值视为您的结果和通货膨胀的性质:)。

我在最后一步通过ROW_NUMBER() 函数的贡献确定了上一列和当前列:

WITH t1 AS
(
 SELECT DISTINCT MAX(Cost) OVER (PARTITION BY Item_Number, Effective_Date) AS Cost,
        Item_Number, Effective_Date
   FROM tab 
  ORDER BY Item_Number, Effective_Date 
), t2 AS
(
 SELECT t1.*, 
        ROW_NUMBER() OVER (PARTITION BY Item_Number ORDER BY Effective_Date DESC) AS rn
   FROM t1  
)
SELECT Item_Number, 
       MAX(CASE WHEN rn = 2 THEN Effective_Date END) AS Previous_Date,
       MAX(CASE WHEN rn = 2 THEN Cost END) AS Previous_Cost,
       MAX(CASE WHEN rn = 1 THEN Effective_Date END) AS Current_Date,
       MAX(CASE WHEN rn = 1 THEN Cost END) AS Current_Cost       
  FROM t2   
 WHERE rn <= 2 
 GROUP BY Item_Number;

Demo

【讨论】:

    【解决方案2】:

    我可以为你推荐以下方法。

    with
        date_t as
        (
            select 1 as item_number, to_date('01/01/2020','mm/dd/yyyy') as effective_date, 8.00 as cost, 11.00 as price from dual union all
            select 1 as item_number, to_date('01/01/2020','mm/dd/yyyy') as effective_date, 8.00 as cost, 10.50 as price from dual union all
            select 2 as item_number, to_date('09/22/2020','mm/dd/yyyy') as effective_date, 6.25  as cost, 6.50 as price from dual union all
            select 1 as item_number, to_date('01/01/2020','mm/dd/yyyy') as effective_date, 8.00 as cost, 10.50 as price from dual union all
            select 1 as item_number, to_date('05/07/2019','mm/dd/yyyy') as effective_date, 7.00 as cost, 10.50 as price from dual union all
            select 1 as item_number, to_date('03/12/2018','mm/dd/yyyy') as effective_date, 6.00 as cost, 10.50 as price from dual union all
            select 2 as item_number, to_date('03/12/2018','mm/dd/yyyy') as effective_date, 6.00  as cost, 6.50 as price from dual union all
            select 2 as item_number, to_date('03/12/2018','mm/dd/yyyy') as effective_date, 6.00  as cost, 6.50 as price from dual union all
            select 1 as item_number, to_date('01/01/2020','mm/dd/yyyy') as effective_date, 7.00 as cost, 10.50 as price from dual union all
            select 1 as item_number, to_date('08/01/2016','mm/dd/yyyy') as effective_date, 5.25 as cost, 10.50 as price from dual 
        )
    select 
        item_number,
        lag(effective_date) over (partition by item_number order by effective_date) as previous_date,
        lag(cost) over (partition by item_number order by effective_date) as previous_cost,
        effective_date as current_date,
        cost as current_cost
    from    
        (
            select
                item_number,
                effective_date,
                max(cost) as cost
            from
                date_t  
            group by
                item_number,
                effective_date
            order by effective_date desc
        ) t 
    

    输出将如下所示。

    ITEM_NUMBER PREVIOUS_DATE   PREVIOUS_COST   CURRENT_DATE    CURRENT_COST
    ----------- -------------   -------------   ------------     ----------- 
    1             null          null            01.08.2016       5.25
    1             01.08.2016    5.25            12.03.2018       6
    1             12.03.2018    6               07.05.2019       7
    1             07.05.2019    7               01.01.2020       8
    2             null          null            12.03.2018       6
    2             12.03.2018    6               22.09.2020       6.25
    

    注意:我在 Oracle 中的另一种日期格式是 dd.mm.yyyy

    【讨论】:

      猜你喜欢
      • 2022-12-09
      • 2011-04-03
      • 2021-07-03
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-01-20
      相关资源
      最近更新 更多