Sql 用于在特定场景中获取oracle中的上一个日期的查询
我在表a中有以下数据,我需要将其与一个计算列一起插入表B中 表A: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
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
我在小提琴上又增加了几行,只是为了测试一下