2009-08-04 36 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

相關問題