我可以使用SQL根据日程信息绘制实际日期吗?

我可以使用SQL根据日程信息绘制实际日期吗?,sql,sql-server,sql-server-2005,tsql,Sql,Sql Server,Sql Server 2005,Tsql,如果我有一个包含暗示特定日期的计划信息的表,那么是否有一个SQL语句可以编写,使用某种交叉连接将该信息转换为实际行 考虑包含以下列的付款计划表: StartDate-计划开始的日期第一笔付款应在该日期到期 期限-计划的月数长度 频率-复发之间的月数 PaymentAmt-付款金额:- 是否有一个SQL语句允许我从上面转到下面 Running SchedID Payment Due Expected Num Date Total ---

如果我有一个包含暗示特定日期的计划信息的表,那么是否有一个SQL语句可以编写,使用某种交叉连接将该信息转换为实际行

考虑包含以下列的付款计划表:

StartDate-计划开始的日期第一笔付款应在该日期到期 期限-计划的月数长度 频率-复发之间的月数 PaymentAmt-付款金额:- 是否有一个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 1 5 05-Jan-2007 5000.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 我使用的是MS SQL Server 2005,不希望很快升级,我已经可以使用一个表变量和while循环来实现这一点,但似乎会应用某种交叉连接,但我不知道这是如何实现的

谢谢你的想法


编辑:我实际上使用的是SQLServer2005,虽然我最初说的是2000。我们并不像我想的那么落后。抱歉。

我使用了表值函数来实现类似的结果。基本上与使用表变量相同,我知道,但我记得我对设计非常满意

在我看来,这个用法最终读得非常好:

/* assumes @startdate and @enddate schedule limits */

SELECT
   p.paymentid,
   ps.paymentnum,
   ps.duedate,
   ps.ret
FROM
   payment p,
   dbo.FUNC_get_payment_schedule(p.paymentid, @startdate, @enddate) ps
ORDER BY p.paymentid, ps.paymentnum

典型的解决方案是使用日历表。您可以扩展它以满足您自己的需要,但它看起来像:

CREATE TABLE Calendar
(
     calendar_date DATETIME NOT NULL,
     is_holiday BIT NOT NULL DEFAULT(0),
     CONSTRAINT PK_Calendar PRIMARY KEY CLUSTERED calendar_date
)

除了is_假日,您还可以添加其他与您相关的列。您可以编写一个脚本,在接下来的10年、100年或1000年内填充该表,您应该已经准备好了。它使您尝试执行的查询变得更加简单,并可以为您提供额外的功能。

尝试使用整数表或更好的方法:和一些日期数学,例如。start+int*freq

我现在无法测试代码,因此请谨慎对待,但我认为下面的内容应该可以回答这个问题:

with q(SchedId, PaymentNum, DueDate, RunningExpectedTotal) as
    (select SchedId,
            1 as PaymentNum,
            StartDate as DueDate,
            PaymentAmt as RunningExpectedTotal
     from PaymentScheduleTable
     union all
     select q.SchedId,
             1 + q.PaymentNum as PaymentNum,
             DATEADD(month, s.Frequency, q.DueDate) as DueDate,
             q.RunningExpectedTotal + s.PaymentAmt as RunningExpectedTotal
     from q
          inner join PaymentScheduleTable s
                  on s.SchedId = q.SchedId
     where q.PaymentNum <= s.Term / s.Frequency)
select *
from q
order by SchedId, PaymentNum

是的,我是这样做的,但在这个过程中,似乎应该有更好的纯度?老实说,我已经有一段时间没有使用SQL了,也许我喜欢这种设计,因为它让我想起了我习惯的编程风格。我完全理解您为什么要使用干净的SQL,我喜欢这个问题。不幸的是,时间表是继承设计的一部分。我不能为了你提到的日历表而放弃它。在另一种情况下,我可能会。无论如何,谢谢。我不是建议你放弃你目前的设计。您可以将日历表与现有表一起使用,按日期连接。这就是他们通常使用的方式。我喜欢这个想法,尽管它不是一个很好的答案。我可能会创建一个函数,它接受一个日期和频率,并将其与交叉应用程序一起使用,这样我就可以在任何计划中重用它。哇!!真热!我刚刚尝试了你的查询,它真的很有效。接下来的一个小时我只花一个小时,希望能弄清楚里面到底发生了什么。谢谢。我现在肯定更聪明了,否则一个小时左右就会变聪明-
with q(SchedId, PaymentNum, DueDate, RunningExpectedTotal) as
    (select SchedId,
            1 as PaymentNum,
            StartDate as DueDate,
            PaymentAmt as RunningExpectedTotal
     from PaymentScheduleTable
     union all
     select q.SchedId,
             1 + q.PaymentNum as PaymentNum,
             DATEADD(month, s.Frequency, q.DueDate) as DueDate,
             q.RunningExpectedTotal + s.PaymentAmt as RunningExpectedTotal
     from q
          inner join PaymentScheduleTable s
                  on s.SchedId = q.SchedId
     where q.PaymentNum <= s.Term / s.Frequency)
select *
from q
order by SchedId, PaymentNum