简体   繁体   中英

SQL Recursive Calculated Date

I have a sql server table:

CREATE TABLE [Workflow].[MilestoneDate](
 [MilestoneDateId] [int] IDENTITY(1,1) NOT NULL,
 [SpecifiedDate] [datetime] NULL,
 [RelativeDays] [int] NULL,
 [RelativeMilestoneDateId] [int] NULL,
 CONSTRAINT [PK_MilestoneDate] PRIMARY KEY CLUSTERED 
(
 [MilestoneDateId] ASC
)WITH (PAD_INDEX  = OFF, STATISTICS_NORECOMPUTE  = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS  = ON, ALLOW_PAGE_LOCKS  = ON) ON [PRIMARY]
) ON [PRIMARY]

GO
ALTER TABLE [Workflow].[MilestoneDate]  WITH CHECK ADD  CONSTRAINT [FK_MilestoneDate_MilestoneDate] FOREIGN KEY([RelativeMilestoneDateId])
REFERENCES [Workflow].[MilestoneDate] ([MilestoneDateId])
GO
ALTER TABLE [Workflow].[MilestoneDate] CHECK CONSTRAINT [FK_MilestoneDate_MilestoneDate]

and it has data that might look like:

Id     Date                          RelDays RelId
49     2010-03-04 00:00:00.000       NULL    NULL
746    NULL                          6       46
747    NULL                          20      746
46     2010-02-18 00:00:00.000       NULL    NULL
48     2010-04-04 00:00:00.000       NULL    NULL
47     2010-05-04 00:00:00.000       NULL    NULL
748    NULL                          14      48

What I need to be able to do is to get the calculated date for each row which is either the Date if there is one, or the Date of the "parent" item (using the RelId) plus the RelDays (which can be recursive).

So for example the calculated date for Id 747 is 20 days + 6 days + 2010-02-18 and therefore 2010-03-16.

try this (uses a CTE which is only available on SQL Server 2005 and up):

DECLARE @YourTable table (Id int, Date datetime, RelDays int, RelId int)
INSERT @YourTable VALUES (49 ,'2010-03-04 00:00:00.000',NULL ,NULL)
INSERT @YourTable VALUES (746, NULL                    ,6    ,46)
INSERT @YourTable VALUES (747, NULL                    ,20   ,746)
INSERT @YourTable VALUES (46 ,'2010-02-18 00:00:00.000',NULL ,NULL)
INSERT @YourTable VALUES (48 ,'2010-04-04 00:00:00.000',NULL ,NULL)
INSERT @YourTable VALUES (47 ,'2010-05-04 00:00:00.000',NULL ,NULL)
INSERT @YourTable VALUES (748, NULL                    ,14   ,48)

;WITH R AS
(
    SELECT id,Date,RelDays,RelId  --get all parents
    FROM @YourTable
    WHERE RelId IS NULL
    UNION ALL    --recursive go through all children, adding the days on
    SELECT
        y.id,r.Date+y.RelDays,y.RelDays,y.RelId
        FROM @YourTable y
            INNER JOIN R ON y.RelId=r.Id
)
select * from R

OUTPUT:

id          Date                    RelDays     RelId
----------- ----------------------- ----------- -----------
49          2010-03-04 00:00:00.000 NULL        NULL
46          2010-02-18 00:00:00.000 NULL        NULL
48          2010-04-04 00:00:00.000 NULL        NULL
47          2010-05-04 00:00:00.000 NULL        NULL
748         2010-04-18 00:00:00.000 14          48
746         2010-02-24 00:00:00.000 6           46
747         2010-03-16 00:00:00.000 20          746

(7 row(s) affected)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM