Sql 用于在特定场景中获取oracle中的上一个日期的查询

Sql 用于在特定场景中获取oracle中的上一个日期的查询,sql,oracle,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

我在表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函数往回遍历来检查负平衡的第一个实例

即使是第一个_值函数也尝试过,但没有得到如何基于负值进行分区


这方面的任何帮助或指导都会非常有用。

这里有一种使用分析函数实现这一点的方法

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);
首先,总和用作分析函数,将组号分配给小于0的连续余额。 最后一个值函数用于查找每组的最后一个-ve余额 最后,根据每个组对结果进行聚合。MAXdate给出最后一个日期,MINdate给出开始日期,两者之差给出天数。
演示。

这里有一种使用分析函数实现这一点的方法

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);
首先,总和用作分析函数,将组号分配给小于0的连续余额。 最后一个值函数用于查找每组的最后一个-ve余额 最后,根据每个组对结果进行聚合。MAXdate给出最后一个日期,MINdate给出开始日期,两者之差给出天数。 演示。

尝试此操作,并使用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;
希望这对您有所帮助。

尝试此操作并使用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;

希望这能帮上忙,朋友。

现在就开始吧

从余额为正的my_表中选择所有记录。 执行自联接并获取所有记录,这些记录的截止日期大于当前行,但金额为负数 一旦我们得到这些数据,我们就把当前行和前一行的日期差大于1的行切掉。然后通过外部子查询过滤结果 最后的select只对行进行分组,并获取已分组的筛选行的最小值和最大值。 查询:

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

我在小提琴上又增加了几行,只是为了测试一下

下面是我的方法

从余额为正的my_表中选择所有记录。 执行自联接并获取所有记录,这些记录的截止日期大于当前行,但金额为负数 一旦我们得到这些数据,我们就把当前行和前一行的日期差大于1的行切掉。然后通过外部子查询过滤结果 最后的select只对行进行分组,并获取已分组的筛选行的最小值和最大值。 查询:

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
我在小提琴上又增加了几行,只是为了测试一下