2009-08-04 58 views
1

我问this question in regard to SQL Server,但什么是对Oracle环境中(10克)的答案吗?我可以使用Oracle SQL从计划信息中绘制实际日期吗?

如果我有一个表,包含调度信息暗示特定的日期,是否有可以写入的信息转化为实际行,使用类似MSSQL的表常见合表情,也许是一个SQL语句?

考虑这些列的付款计划表:

  • 起始日期 - 计划开始日期(第1款项应在此日期)
  • 期限 - 长度中的月日程表
  • 频率 - 重复之间的月份数
  • PaymentAmt - 付款金额:-)
 
SchedID StartDate Term Frequency PaymentAmt 
------------------------------------------------- 
1  05-Jan-2003 48 12   1000.00 
2  20-Dec-2008 42 6   25.00 

是否有一个SQL语句,让我从上面到下面?

 
           Running 
SchedID Payment Due   Expected 
     Num  Date   Total 
-------------------------------------- 
1  1  05-Jan-2003 1000.00 
1  2  05-Jan-2004 2000.00 
1  3  05-Jan-2005 3000.00 
1  4  05-Jan-2006 4000.00 
2  1  20-Dec-2008 25.00 
2  2  20-Jun-2009 50.00 
2  3  20-Dec-2009 75.00 
2  4  20-Jun-2010 100.00 
2  5  20-Dec-2010 125.00 
2  6  20-Jun-2011 150.00 
2  7  20-Dec-2011 175.00 

您的想法得到了赞赏。

回答

1

我没有要回答我自己的问题,但我现在做的工作与甲骨文和我不得不学习一些新的Oracle味的东西。

反正CONNECT BY语句是非常好的 - 是的,比MSSQL的hierchical查询方法,并好得多使用结构,我能够产生一个非常干净的查询做什么,我一直在寻找:

SELECT DISTINCT 
    t.SchedID 
    ,level as PaymentNum 
    ,add_months(T.StartDate,level - 1) as DueDate 
    ,(level * t.PaymentAmt) as RunningTotal 
FROM SchedTest t 
CONNECT BY level <= (t.Term/t.Frequency) 
ORDER BY t.SchedID, level 

我唯一剩下的问题是我不得不使用DISTINCT,因为我无法弄清楚如何从DUAL(友好的单行Oracle表)中选择我的行,而不是从我的日程表数据表中选择我的行,至少2行。如果我可以用FROM DUAL来完成上述操作,那么我的DISTINCT指标就没有必要了。有什么想法吗?

除此之外,我觉得这很不错。 Et tu?

1

甲骨文实际上有使用CONNECT BY子句的分层查询语法。 SQL Server的使用WITH子句看起来像一个黑客在对比:

SELECT t.SchedId, 
      CASE LEVEL 
      WHEN 1 THEN 
       t.StartDate 
      ELSE 
       ADD_MONTHS(t.StartDate, t.frequency) 
      END 'DueDate', 
      CASE LEVEL 
      WHEN 1 THEN 
       t.PaymentAmt 
      ELSE 
       SUM(t.paymentAmt) 
      END 'RunningExpectedTotal' 
     FROM PaymentScheduleTable t 
    WHERE t.PaymentNum <= t.Term/t.Frequency 
CONNECT BY PRIOR t.startdate = t.startdate 
    GROUP BY t.schedid, t.startdate, t.frequency, t.paymentamt 
    ORDER BY t.SchedId, t.PaymentNum 

我不是100%,这是 - 我更有信心使用:

SELECT t.SchedId, 
      t.StartDate 'DueDate', 
      t.PaymentAmt 'RunningExpectedTotal' 
     FROM PaymentScheduleTable t 
    WHERE t.PaymentNum <= t.Term/t.Frequency 
CONNECT BY PRIOR t.startdate = t.startdate 
    ORDER BY t.SchedId, t.PaymentNum 

...但它不包括当你在链处理第二+条目以添加个月&款项的数额来处理逻辑。根据所需的细节,可以使用GROUP BY CUBE或ROLLUP进行求和。

+0

我在尝试你的建议,但我没有太多的运气。第二个查询导致无限循环。我如何避免这种情况? – witttness 2009-08-04 19:05:11

+0

我不确定CONNECT BY PRIOR是否支持指向同一列 - 没有Oracle进行测试。我也错过了“哪里q.PaymentNum <= s.Term/s.Frequency” – 2009-08-04 19:25:39

+0

我更新了在开始日期之前的连接,因为这实际上是指示顺序,但我不知道是否可以指向相同柱。 – 2009-08-04 19:49:56

1

我不明白为什么5天付款为schedid = 1和7赛德= 2?

48/12 = 4和42/6 = 7。因此,我预期schedid = 1

反正使用模型第4天付款:

create table PaymentScheduleTable 
(schedid number(10) 
, startdate date 
, term  number(3) 
, frequency number(3) 
, paymentamt number(5) 
); 

insert into PaymentScheduleTable 
values (1,to_date('05-01-2003','dd-mm-yyyy') 
, 48 
, 12 
, 1000); 

insert into PaymentScheduleTable 
values (2,to_date('20-12-2008','dd-mm-yyyy') 
, 42 
, 6 
, 25); 

commit; 

而现在的选择与模型子句:

select schedid, to_char(duedate,'dd-mm-yyyy') duedate, expected, i paymentnum 
from paymentscheduletable 
model 
partition by (schedid) 
dimension by (1 i) 
measures (
    startdate duedate 
, paymentamt expected 
, term 
, frequency) 
rules 
(expected[for i from 1 to term[1]/frequency[1] increment 1] 
    = nvl(expected[cv()-1],0) + expected[1] 
, duedate[for i from 1 to term[1]/frequency[1] increment 1] 
    = add_months(duedate[1], (cv(i)-1) * frequency[1]) 
) 
order by schedid,i; 

此输出:

SCHEDID DUEDATE  EXPECTED PAYMENTNUM 
---------- ---------- ---------- ---------- 
     1 05-01-2003  1000   1 
     1 05-01-2004  2000   2 
     1 05-01-2005  3000   3 
     1 05-01-2006  4000   4 
     2 20-12-2008   25   1 
     2 20-06-2009   50   2 
     2 20-12-2009   75   3 
     2 20-06-2010  100   4 
     2 20-12-2010  125   5 
     2 20-06-2011  150   6 
     2 20-12-2011  175   7 


11 rows selected. 
+0

对于SchedID 1你是对的。问题中的例子应该只有4个支付,而不是5个。我正在改变这个问题。 – witttness 2009-08-05 20:24:44

相关问题