查询在特定方案中获取oracle中的上一个日期

时间:2013-09-14 10:00:52

标签: sql oracle

我在表格 A 中有以下数据,我需要将其插入表格 B 以及一个计算列。

表A:

Account_No |  Balance   |  As_on_date  
1001       |-100        |  1-Jan-2013  
1001       |-150        |  2-Jan-2013  
1001       | 200        |  3-Jan-2013  
1001       |-250        |  4-Jan-2013  
1001       |-300        |  5-Jan-2013  
1001       |-310        |  6-Jan-2013

表B:

在表B中,当余额为负时,应该没有显示天数 它已成为负面的日期。

因此,对于2013年1月6日,此表应显示以下数据:

Account_No |  Balance   |  As_on_date   | Days_passed | Start_date   
1001       |    -310    |    6-Jan-2013 |    3        |     4-Jan-2013

在这里,没有几天应该是最近时间余额变为负数的日子 不是来自旧条目。

我需要编写一个SQL查询来获取过去的日期和开始日期 平衡已经消极。

我尝试使用Lag分析函数来制定查询,但我没有成功。

如何通过使用LAG函数遍历来检查第一个负余额实例?

即使是first_value函数也尝试了,但没有根据负值获取如何对其进行分区。

对此的任何帮助或指示都会非常有用。

3 个答案:

答案 0 :(得分:2)

以下是使用分析函数实现此目的的方法。

INSERT INTO tableb
   WITH tablea_grouped1
        AS (SELECT account_no,
                   balance,
                   as_on_date,
                   SUM (CASE WHEN balance >= 0 THEN 1 ELSE 0 END)
                      OVER (PARTITION BY account_no ORDER BY as_on_date)
                      grp
              FROM tablea),
        tablea_grouped2
        AS (SELECT account_no,
                   balance,
                   as_on_date,
                   grp,
                   LAST_VALUE (
                      balance)
                   OVER (
                      PARTITION BY account_no, grp
                      ORDER BY as_on_date
                      ROWS BETWEEN UNBOUNDED PRECEDING
                           AND     UNBOUNDED FOLLOWING)
                      closing_balance
              FROM tablea_grouped1
             WHERE balance < 0 
               AND grp != 0 --keep this, if starting negative balance is to be ignored
           )
     SELECT account_no,
            closing_balance,
            MAX (as_on_date),
            MAX (as_on_date) - MIN (as_on_date) + 1,
            MIN (as_on_date)
       FROM tablea_grouped2
   GROUP BY account_no, grp, closing_balance
   ORDER BY account_no, MIN (as_on_date);
  • 首先,SUM用作分析函数,将组编号分配给小于0的连续余额。
  • 然后使用LAST_VALUE函数查找每个组中的最后一次余额
  • 最后,根据每个组汇总结果。 MAX(日期)给出最后一个日期,MIN(日期)给出开始日期,两者的差异给出天数。

sqlfiddle的演示。

答案 1 :(得分:2)

尝试此操作并使用gone_negative计算指定的列值以插入另一个表:

select temp.account_no,
       temp.balance,
       temp.prev_balance,
       temp.on_date,
       temp.prev_on_date,
       case
         WHEN (temp.balance < 0 and temp.prev_balance >= 0) THEN
          1
         else
          0
       end as gone_negative
  from (select account_no,
               balance,
               on_date,
               lag(balance, 1, 0) OVER(partition by account_no ORDER BY account_no) prev_balance,
               lag(on_date, 1) OVER(partition by account_no ORDER BY account_no) prev_on_date
          from tblA
         order by account_no) temp;

希望这有助于朋友。

答案 2 :(得分:0)

现在正在进行中。

  1. 选择余额为正的my_table的所有记录。
  2. 执行自我加入并获取as_on_date大于当前行的所有记录,但amounts为负数
  3. 一旦我们得到这些内容,我们就截止WHEREdate difference之间的行row as_on_date > 1 outer sub query select min, max。然后,我们会将结果过滤为SELECT account_no, min(case when row_number = 1 then balance end) as balance, max(mt2_date) as As_on_date, max(mt2_date) - mt1_date as Days_passed, min(mt2_date) as Start_date FROM ( SELECT *, MIN(break_date) OVER( PARTITION BY mt1_date ) AS min_break_date, ROW_NUMBER() OVER( PARTITION BY mt1_date ORDER BY mt2_date desc ) AS row_number FROM ( SELECT mt1.account_no, mt2.balance, mt1.as_on_date as mt1_date, mt2.as_on_date as mt2_date, case when mt2.as_on_date - lag(mt2.as_on_date,1) over () > 1 then mt2.as_on_date end as break_date FROM my_table mt1 JOIN my_table mt2 ON ( mt2.balance < mt1.balance AND mt2.as_on_date > mt1.as_on_date ) WHERE MT1.balance > 0 order by mt1.as_on_date, mt2.as_on_date ) sub_query ) T WHERE min_break_date is null OR mt2_date < min_break_date GROUP BY mt1_date, account_no
  4. 最终{{1}}只对行进行分组,并获取已分组的已过滤行的{{1}}值。
  5. 查询:

    {{1}}

    SQLFIDDLE

    我在FIDDLE中添加了几行,只是为了测试它