用于在SQL Server中添加两个日期之间缺少的StartDate的SQL代码

jk9hmnmh  于 2022-12-26  发布在  SQL Server
关注(0)|答案(1)|浏览(126)

我有下面的表排序的客户ID,合同ID和生效日期。一个客户有多个合同ID和它的各自生效日期。

所需的输出如下所示,其中新的FYStartDate列应添加clientID的后续contractID的2个日期之间缺失的FYStartDate(在此方案中,Fiscal Year从每年的6月1日开始)

如果您能分享所需的SQL代码,我将不胜感激。

我将附加SQL代码以生成第一个表

CREATE TABLE [client] (
[clientid] [int] NULL,
[contractid] [int] NULL,
[effectivedate] [date] NULL
) ON [PRIMARY]
GO 

insert into [client] values
('228','2','6/1/2003'),('228','136','6/1/2004'),('228','242','6/1/2008'), 
('228','337','12/1/2012'),('228','584','6/1/2017'),('14216','319','5/1/2013'), 
('14216','355','6/1/2013'),('14216','739','6/1/2020'),('14216','10','3/1/2021'), 
('14216','1009','6/1/2021')
mjqavswn

mjqavswn1#

这有点复杂,因为@MatBailie建议使用更多结构化数据。要完成您的要求,每条记录都需要知道合同生效之前和之后的时间。我认为您需要尝试排序,因为我不太清楚如何排序结果...按客户ID、合同ID、日期等?
更新:见注解。更改了一些CTE,JOINS和ORDER BY,以便更好地按clientid分区。

CREATE TABLE [client] (
[clientid] [int] NULL,
[contractid] [int] NULL,
[effectivedate] [date] NULL
) ON [PRIMARY]
;

insert into [client] values
('228','2','6/1/2003'),('228','136','6/1/2004'),('228','242','6/1/2008'), 
('228','337','12/1/2012'),('228','584','6/1/2017'),('14216','319','5/1/2013'), 
('14216','355','6/1/2013'),('14216','739','6/1/2020'),('14216','10','3/1/2021'), 
('14216','1009','6/1/2021')
;

--Need a sequence of numbers to create a sequence of fiscal years.
WITH x AS (
  SELECT * FROM (VALUES (0),(1),(2),(3),(4),(5),(6),(7),(8),(9)) as x(a)
), y as (
  SELECT ROW_NUMBER() OVER(ORDER BY tens.a, ones.a) as row_num
  FROM x as ones, x as tens
), fiscYears as (
  SELECT
    fyStart = DATEFROMPARTS(2000 + y.row_num -1, 6, 1)
    , fyEnd = DATEFROMPARTS(2000 + y.row_num, 5, 31)
  FROM y

--Need to order the client records by effective date.
--From updated question... looks like we are reporting by clientid.
), clientOrd as (
  SELECT c2.*, ROW_NUMBER() OVER(PARTITION BY c2.clientid ORDER BY c2.effectivedate) as row_num
      FROM client c2

--For each contract, get the previous and next contracts by effective date.
), clientWNext as (
  SELECT c.*
    , cNext.effectivedate as nextEffectiveDate
    , cPrev.effectivedate as prevEffectiveDate
  FROM clientOrd as c
    LEFT JOIN clientOrd as cNext
      ON cNext.clientid = c.clientid
      AND cNext.row_num = c.row_num + 1
    LEFT JOIN clientOrd as cPrev
      ON cPrev.clientid = c.clientid
      AND cPrev.row_num = c.row_num - 1
)
SELECT
  c.clientid
  , cwn.contractid
  , CASE WHEN cwn.effectiveDate >= fy.fyStart AND cwn.effectiveDate <= fy.fyEnd 
      THEN  cwn.effectivedate
      ELSE null
    END as effectivedate
  , fy.fyStart
FROM fiscYears as fy
  --To get a full FY range for each client, we join to a distinct list of clients.
  JOIN (
    SELECT DISTINCT clientid FROM client
  ) as c
    ON 1=1

  --Need to join the list of contracts.
  INNER JOIN clientWNext as cwn
    ON cwn.clientid = c.clientid
  
    --This is the main join criteria where the effective date is within the fy year start/end.
    AND ((
      cwn.effectivedate >= fy.fyStart
      AND cwn.effectivedate <= fy.fyEnd
    ) 

    --This is the "alternate" join criteria where the previous contrat is still in effect
    --but there is no new contract to supercede the previous.
    OR (
      cwn.prevEffectiveDate < fy.fyStart
      AND cwn.effectiveDate < fy.fyStart
      AND (cwn.nextEffectiveDate > fy.fyEnd OR cwn.nextEffectiveDate IS NULL)
    ))

--Limiting fiscal year date range.
WHERE fy.fyStart >= '1/1/2003'
  AND fy.fyStart < '1/1/2024'
ORDER BY c.clientid, fy.fyStart, cwn.effectivedate

| 客户|缩节|有效日期|fy开始|
| - ------| - ------| - ------| - ------|
| 二百二十八|第二章|二○ ○三年六月一日|二○ ○三年六月一日|
| 二百二十八|一百三十六|二○ ○四年六月一日|二○ ○四年六月一日|
| 二百二十八|一百三十六|* 无效 |二零零五年六月一日|
| 二百二十八|一百三十六|
无效 |二○ ○六年六月一日|
| 二百二十八|一百三十六|
无效 |二零零七年六月一日|
| 二百二十八|二四二|二○ ○八年六月一日|二○ ○八年六月一日|
| 二百二十八|二四二|
无效 |二○ ○九年六月一日|
| 二百二十八|二四二|
无效 | 2010年6月1日|
| 二百二十八|二四二|
无效 | 2011年6月1日|
| 二百二十八|三百三十七|2012年12月1日|2012年6月1日|
| 二百二十八|三百三十七|
无效 | 2013年6月1日|
| 二百二十八|三百三十七|
无效 | 2014年6月1日|
| 二百二十八|三百三十七|
无效 | 2015年6月1日|
| 二百二十八|三百三十七|
无效 | 2016年6月1日|
| 二百二十八|五八四|2017年6月1日|2017年6月1日|
| 二百二十八|五八四|
无效 | 2018年6月1日|
| 二百二十八|五八四|
无效 | 2019年6月1日|
| 二百二十八|五八四|
无效 | 2020年6月1日|
| 二百二十八|五八四|
无效 |二○二一年六月一日|
| 二百二十八|五八四|
无效 | 2022年6月1日|
| 二百二十八|五八四|
无效 |二○二三年六月一日|
| 小行星14216|三一九|2013年5月1日|2012年6月1日|
| 小行星14216|三五五|2013年6月1日|2013年6月1日|
| 小行星14216|三五五|
无效 | 2014年6月1日|
| 小行星14216|三五五|
无效 | 2015年6月1日|
| 小行星14216|三五五|
无效 | 2016年6月1日|
| 小行星14216|三五五|
无效 | 2017年6月1日|
| 小行星14216|三五五|
无效 | 2018年6月1日|
| 小行星14216|三五五|
无效 *| 2019年6月1日|
| 小行星14216|七三九|2020年6月1日|2020年6月1日|
| 小行星14216|十个|二○二一年三月一日|2020年6月1日|
| 小行星14216|小行星1009|二○二一年六月一日|二○二一年六月一日|
| 小行星14216|小行星1009| * 无效 *| 2022年6月1日|
| 小行星14216|小行星1009| * 无效 *|二○二三年六月一日|
fiddle

相关问题