2

我在表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

在这里,no of days 应该是最近一段时间余额变为负数的天数,而不是旧条目的天数。

我需要编写一个 SQL 查询来获取过去的天数和余额变为负数的开始日期。

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

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

甚至对该first_value函数进行了尝试,但没有得到如何基于负值对其进行分区。

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

4

3 回答 3

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 函数查找每个组中的最后一个 -ve 余额
  • 最后,根据每个组汇总结果。MAX(date) 给出最后日期,MIN(date) 给出开始日期,两者的差给出天数。

sqlfiddle演示。

于 2013-09-14T12:43:44.117 回答
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;

希望这对朋友有帮助。

于 2013-09-14T13:11:18.850 回答
0

这是在做的路上。

  1. 选择my_table余额为正的所有记录。
  2. 进行自连接并获取所有 aas_on_date大于当前行的记录,但 a 为amounts负数
  3. 一旦我们得到这些,我们就切断当前和前一个之间的行WHERE,因为is 。然后我们过滤结果date differencerowas_on_date> 1outer sub query
  4. Finalselect只是对行进行分组并获取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

SQLFIDDLE

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

于 2013-09-14T15:04:10.910 回答