Tsql 注册段-分组时也考虑限制日期

Tsql 注册段-分组时也考虑限制日期,tsql,recursion,Tsql,Recursion,我有以下数据集 enrollid EnrollmentEffectiveDate EnrollmentTermDate EnrollmentRestrictionEffectiveDate EnrollmentRestrictionTermDate ES00424092 4/1/2011 9/30/2013 10/1/2011 10/31/2011 ES00424092 4/1/2011 9/30/2013 9/1/2013 9

我有以下数据集

enrollid     EnrollmentEffectiveDate    EnrollmentTermDate EnrollmentRestrictionEffectiveDate   EnrollmentRestrictionTermDate
ES00424092      4/1/2011    9/30/2013   10/1/2011   10/31/2011
ES00424092      4/1/2011    9/30/2013   9/1/2013    9/30/2013
硕士注册部分由其自己的范围定义,即2011年4月1日至2013年9月30日。但如果你看到有2个限制段。我希望将此数据集按如下方式断开

enrollid    EnrollmentEffectiveDate EnrollmentTermDate  EnrollmentStatus
ES00424092      4/1/2011    9/30/2011    ACTIVE
ES00424092      10/1/2011   10/31/2011  RESTRICTED
ES00424092      11/1/2011   8/31/2013   ACTIVE
ES00424092      9/1/2013    9/30/2013   RESTRICTED
我们基本上是将上述部分划分为活跃和受限的部分


这是一个注册ID的示例。我必须编写一个tSQL过程来为接近150K的注册ID执行此操作。在多个时期可能会有限制,我们必须相应地应用逻辑。朋友们,有什么建议吗?

我想我已经找到了我需要的答案。我是这样做的`

DECLARE @d TABLE(from_date DATE, to_date DATE);

/* SELECT ALL THE RECORDS THAT ARE ELIGIBLE 2 YEARS BEFORE AND AFTER */
IF OBJECT_ID('tempdb..##MonthList') IS NOT NULL DROP TABLE ##MonthList
IF OBJECT_ID('tempdb..##EnrollKeys') IS NOT NULL DROP TABLE ##EnrollKeys

RAISERROR ('TEMP TABLES DROPPED SUCCESSFULLY IF EXISTED', 0, 1) WITH NOWAIT

SELECT
     PK_EnrollKeys = IDENTITY(INT,1,1)
    ,LTRIM(RTRIM(EnrollID)) [EnrollID]
    ,EK.effdate [EffectiveDate]
    ,CASE WHEN EK.termdate = '12-31-2078' THEN CAST('12'+ '-'+ '31' + '-' + CAST(YEAR(GETDATE()) AS VARCHAR(10)) AS DATETIME) ELSE EK.termdate END [TermDate]
INTO
    ##EnrollKeys
FROM
    PlanData.dbo.enrollkeys EK (NOLOCK)
WHERE
    LEN(enrollid) > 0
ORDER BY
     EK.enrollid
    ,EK.effdate
    ,EK.termdate

SET @RowCount = @@ROWCOUNT 
SET @THETIME = CONVERT(VARCHAR(20),GETDATE(),120)
RAISERROR('%i ROWS INSERTED TO ##EnrollKeys AT %s.',0,1,@RowCount,@THETIME) WITH NOWAIT

/**********************************************************************************************************
    BREAK THE EXISTING ENROLLMENT SEGMENT INTO MONTHLY GRANULAR LEVEL SEGMENTS FOR EASY GROUPING LATER
**********************************************************************************************************/

/* STEP 1: BUILD A MONTHS TABLE FOR ALL MONTHS BETWEEN THE MIN ENROLLKEY EFFECTIVE DATE AND THE 
           MAX ENROLL KEY TERM DATE (WILL DEFAULT 12-31-2078 TO 12-31-2015 TO RESTRICT THE TOTAL RECORDS
           WILL FOLLOW THE CTE APPROACH TO GENERATE THIS AS IT IS EASY AND FAST.
*/
INSERT @d VALUES ('1980-01-01',(SELECT MAX(TermDate) FROM ##EnrollKeys))
;WITH n(n) AS 
(
  SELECT ROW_NUMBER() OVER (ORDER BY [object_id])-1 FROM sys.all_columns
),
d(n,f,t,md,bp,ep) AS 
(
SELECT 
     n.n
    ,d.from_date
    ,d.to_date
    ,DATEDIFF(MONTH, d.from_date, d.to_date)
    ,DATEADD(MONTH, n.n, DATEADD(DAY, 1-DAY(from_date), from_date))
    ,DATEADD(MONTH, n.n+1, DATEADD(DAY, 0-DAY(from_date), from_date))
FROM 
    n 
INNER JOIN 
    @d d 
ON 
    d.to_date >= DATEADD(MONTH, n.n-1, d.from_date)
)
SELECT 
     f [OriginalStartDate]
    ,t [OriginalEndDate]
    ,CASE n WHEN 0  THEN f ELSE bp END [StartDate]
    ,CASE n WHEN md THEN t ELSE ep END [EndDate]
INTO
    ##MonthList
FROM 
    d 
WHERE 
    md >= n
ORDER BY 
     f
    ,t

SET @RowCount = @@ROWCOUNT 
SET @THETIME = CONVERT(VARCHAR(20),GETDATE(),120)
RAISERROR('%i ROWS INSERTED TO ##MonthList AT %s.',0,1,@RowCount,@THETIME) WITH NOWAIT

/* NOW THE ACTUAL BREAK HAPPENS FOR EVERY ENROLLID'S ENROLLMENT SEGMENTS */
IF OBJECT_ID('tempdb..##EnrollmentMaster') IS NOT NULL DROP TABLE ##EnrollmentMaster
SELECT
     T.EnrollID
    ,EffectiveDate
    ,TermDate
    ,M1.StartDate
    ,M1.EndDate
    ,0 [MonthHoldIndicator]
INTO
    ##EnrollmentMaster
FROM
    ##EnrollKeys T
INNER JOIN 
    ##MonthList M1
ON  
    T.EffectiveDate <= M1.StartDate
    AND T.TermDate >= M1.EndDate
ORDER BY
    EnrollID

SET @RowCount = @@ROWCOUNT 
SET @THETIME = CONVERT(VARCHAR(20),GETDATE(),120)
RAISERROR('%i ROWS INSERTED TO ##EnrollmentMaster AT %s.',0,1,@RowCount,@THETIME) WITH NOWAIT

/* UPDATE THE HOLD INDICATOR FROM THE ENROLL RESTRICTION TABLE AS IT IS STORED AT A MONTHLY LEVEL */
UPDATE
    TT
SET
    TT.MonthHoldIndicator = 1
FROM
    ##EnrollmentMaster TT
INNER JOIN
    PlanData.dbo.enrollrestriction ER (NOLOCK)
ON
    TT.EnrollID = LTRIM(RTRIM(ER.enrollid))
    AND TT.StartDate BETWEEN ER.effdate AND ER.termdate
    AND override = 0 -- ANYTHING WITH OVERRIDE 1 IS NOT CONSIDERED A VALID RESTRICTION 

SET @RowCount = @@ROWCOUNT 
SET @THETIME = CONVERT(VARCHAR(20),GETDATE(),120)
RAISERROR('%i ROWS UPDATED FOR MONTHHOLDINDICATOR FIELD IN ##EnrollmentMaster AT %s.',0,1,@RowCount,@THETIME) WITH NOWAIT

/* CREATE NON-CLUSTERED INDEXES ON THE ENROLLID COLUMN & HOLDINDICATOR COLUMNS AS THEY WILL BE USED LATER IN JOINS */
CREATE INDEX IX_##EnrollmentMaster_EnrollID ON ##EnrollmentMaster (EnrollID)
CREATE INDEX IX_##EnrollmentMaster_MonthHoldIndicator ON ##EnrollmentMaster (MonthHoldIndicator)

RAISERROR ('NON CLUSTERED INDEXES CREATED SUCCESSFULLY ON ENROLLID & MONTHHOLDINDICATOR COLUMNS ON "##EnrollmentMaster"', 0, 1) WITH NOWAIT

/* NOW THAT WE HAVE THE MONTHLY ENROLLMENTS AND THE CORRESPOINDING HOLD SEGMENTS START TO GROUP BY ASSIGNING DISTINCT IDS TO
   EVERY GROUPING BASED ON START DATE SO THAT WHEN WE GROUP THEM AT THAT ID LEVEL AND THE START & TERM DATES */

IF OBJECT_ID('tempdb..#TEMP') IS NOT NULL DROP TABLE #TEMP  -- THIS TABLE IS TO GENERATE UNIQUE KEYS FOR EVERY RECORD IN ENROLLMENTMASTER TABLE
CREATE TABLE #TEMP
(
     [Key] INT IDENTITY(1, 1)
    ,[EnrollID] NVARCHAR(200)
    ,[StartDate] DATETIME
    ,[EndDate] DATETIME
    ,[MonthHoldIndicator] INT
    )
RAISERROR ('TEMP TABLE BY NAME #TEMP CREATED SUCCESSFULLY', 0, 1) WITH NOWAIT

/* INSERT RECORDS FROM THE #ENROLLMENTMASTER TO THIS #TEMP */
INSERT
    #TEMP
(
     EnrollID
    ,StartDate
    ,EndDate
    ,MonthHoldIndicator
)
SELECT
     EnrollID
    ,StartDate
    ,EndDate
    ,MonthHoldIndicator
FROM
    ##EnrollmentMaster

SET @RowCount = @@ROWCOUNT 
SET @THETIME = CONVERT(VARCHAR(20),GETDATE(),120)
RAISERROR('%i ROWS INSERTED TO #TEMP AT %s.',0,1,@RowCount,@THETIME) WITH NOWAIT


IF OBJECT_ID('tempdb..#TEMP1') IS NOT NULL DROP TABLE #TEMP1
SELECT 
     [Key] 
    ,[EnrollID]
    ,[StartDate]
    ,[EndDate]
    ,[MonthHoldIndicator]
    ,[Key] - ROW_NUMBER () OVER (PARTITION BY [EnrollID],[MonthHoldIndicator] ORDER BY [Key]) AS [Grp] -- THIS IS THE MAIN PART IN THIS CODE THAT GENERATES A UNIQUE ID FOR GROUPING LATER WHICH IS BASED ON THE KEY FIELD THAT WAS CREATED IN #TEMP TABLE
INTO
    #TEMP1
FROM 
    #TEMP
ORDER BY 
    [Key]

SET @RowCount = @@ROWCOUNT 
SET @THETIME = CONVERT(VARCHAR(20),GETDATE(),120)
RAISERROR('%i ROWS INSERTED TO #TEMP1 AT %s.',0,1,@RowCount,@THETIME) WITH NOWAIT

/* NOW INSERT ALL THIS GROUPED ENROLLMENT RECORDS TO A ENROLLMENTALL GLOBAL TEMP TABLE GROUPING BY THE GRP VALUE CREATED IN #TEMP1 TABLE */
IF OBJECT_ID('tempdb..##EnrollmentAll') IS NOT NULL DROP TABLE ##EnrollmentAll  
SELECT
     [EnrollID]
    ,[Grp]
    ,MonthHoldIndicator
    ,MIN([StartDate]) [EffectiveDate]
    ,MAX([EndDate]) [TermDate]
INTO
    ##EnrollmentAll
FROM
    #TEMP1
GROUP BY
    [EnrollID]
    ,[Grp]
    ,MonthHoldIndicator
ORDER BY
    EnrollID
    ,[EffectiveDate]
    ,[TermDate]

SET @RowCount = @@ROWCOUNT 
SET @THETIME = CONVERT(VARCHAR(20),GETDATE(),120)
RAISERROR('%i ROWS INSERTED TO ##EnrollmentAll AT %s.',0,1,@RowCount,@THETIME) WITH NOWAIT

/* UPDATE THE ORIGINAL 12-31-2078 VALES BACK TO THAT FOR THE ONES THAT SAYS 12-31-2015 */
UPDATE
    TT
SET
    TT.TermDate = '12-31-2078'
FROM
    ##EnrollmentAll TT
INNER JOIN
    PlanData.dbo.enrollkeys EK (NOLOCK)
ON
    TT.EnrollID = EK.enrollid
    AND EK.termdate = '12-31-2078'
    AND TT.TermDate = '12-31-2015'

SET @RowCount = @@ROWCOUNT 
SET @THETIME = CONVERT(VARCHAR(20),GETDATE(),120)
RAISERROR('%i ROWS UPDATED TO 12-31-2078 IN ##EnrollmentAll TABLE AT %s.',0,1,@RowCount,@THETIME) WITH NOWAIT

/*******************************************************************************************************************
    INSERT ALL THE RECORDS FROM THE ##ENROLLMENTALL TABLE TO a MAIN dbo.ENROLLMENTMASTER TABLE
*******************************************************************************************************************/
IF  EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[EnrollmentMaster]') AND type in (N'U'))
DROP TABLE [dbo].[EnrollmentMaster]
SELECT
     PK_EnrollmentMaster = IDENTITY(INT,1,1)
    ,EnrollID
    ,EffectiveDate [EnrollmentEffectiveDate]
    ,TermDate [EnrollmentTerminationdate]
    ,MonthHoldIndicator [HoldIndicator]
INTO
    SFHP_ReportDB.dbo.EnrollmentMaster
FROM
    ##EnrollmentAll
ORDER BY
     EnrollID
    ,EffectiveDate
    ,TermDate


SET @RowCount = @@ROWCOUNT 
SET @THETIME = CONVERT(VARCHAR(20),GETDATE(),120)
RAISERROR('%i ROWS INSERTED TO "SFHP_REPORTDB.dbo.EnrollmentMaster" FROM ##EnrollmentAll AT %s.',0,1,@RowCount,@THETIME) WITH NOWAIT

/* MAKE THE PK_Authorization COLUMN A PRIMARY KEY COLUMN */
IF NOT EXISTS 
    (
        SELECT 
            * 
        FROM 
            INFORMATION_SCHEMA.TABLE_CONSTRAINTS 
        WHERE 
            CONSTRAINT_TYPE = 'PRIMARY KEY' 
        AND 
            TABLE_NAME = 'EnrollmentMaster' 
        AND 
            TABLE_SCHEMA ='dbo'
    )
BEGIN
   ALTER TABLE dbo.EnrollmentMaster ADD CONSTRAINT PK_EnrollmentMaster PRIMARY KEY (PK_EnrollmentMaster)
END
ELSE
BEGIN
   PRINT 'PRIMARY KEY CONSTRAINT ALREADY EXISTS'
END

RAISERROR ('PRIMARY KEY CONSTRAINT CREATED ON TABLE "SFHP_ReportDB.dbo.EnrollmentMaster"', 0, 1) WITH NOWAIT

/* CREATE INDEXES ON THE COLUMNS AS NEEDED */
CREATE INDEX IX_EnrollmentMaster_EnrollID ON SFHP_ReportDB.dbo.EnrollmentMaster  ([EnrollID])
CREATE INDEX IX_EnrollmentMaster_HoldIndicator ON SFHP_ReportDB.dbo.EnrollmentMaster  ([HoldIndicator])

RAISERROR ('NON CLUSTERED INDEXES CREATED SUCCESSFULLY ON ID FIELDS ON "SFHP_ReportDB.dbo.EnrollmentMaster"', 0, 1) WITH NOWAIT


/* DROP ALL THE TEMP TABLES NOW TO CLEAN UP TEMP DB SPACE */
IF OBJECT_ID('tempdb..##EnrollmentMaster') IS NOT NULL DROP TABLE ##EnrollmentMaster
IF OBJECT_ID('tempdb..#TEMP') IS NOT NULL DROP TABLE #TEMP  
IF OBJECT_ID('tempdb..#TEMP1') IS NOT NULL DROP TABLE #TEMP1    
IF OBJECT_ID('tempdb..##EnrollmentAll') IS NOT NULL DROP TABLE ##EnrollmentAll  

RAISERROR ('TEMP TABLES DROPPED SUCCESSFYLLY', 0, 1) WITH NOWAIT

建议:试着发布你的代码并解释什么不起作用。我们将尽力帮助您解决这个问题。使用适当的软件MySQL、Oracle、DB2。。。和版本,例如sql-server-2014。语法和特征的差异通常会影响答案。