SQL Server - 按给定日期

时间:2018-06-02 06:01:40

标签: sql-server

我有一个表存储一个Id和一个有效期,表明它何时处于活动状态

PortfolioId StartDate                 EndDate
1           2018-01-01 00:00:00.000   2018-05-31 00:00:00.000
2           2017-01-01 00:00:00.000   2018-05-31 00:00:00.000

我有另一个表,它存储与上述Id相关的组件,并且也有一个有效期。对于表1中的任何给定条目,表2可以有更多的条目。

PortfolioComponentId    PortfolioId SplitDate
1                       1           2018-02-28 00:00:00.000
2                       1           2018-03-31 00:00:00.000

3                       2           2017-03-31 00:00:00.000
4                       2           2017-09-20 00:00:00.000
5                       2           2018-01-15 00:00:00.000

我有一段时间来运行查询 即

StartDate : 30-JUN-2017
End date  : 15-MAY-2018

我一直在寻找如下结果,表1中的数据根据​​表2中的数据进行分割

PortfolioId StartDate                 EndDate
1           2018-01-01 00:00:00.000   2018-02-28 00:00:00.000
1           2018-03-01 00:00:00.000   2018-03-31 00:00:00.000 - Starts from End date + 1 from the prev row
1           2018-04-01 00:00:00.000   2018-05-15 00:00:00.000

2           2017-06-30 00:00:00.000   2017-09-20 00:00:00.000 - Starts from Seach date [Portfolio component Id 3 ignored as it falls outside of search date range]
2           2017-09-21 00:00:00.000   2018-01-15 00:00:00.000
2           2018-01-16 00:00:00.000   2018-05-15 00:00:00.000 - Ends by seach end date
  

数据设置 - 万一有帮助

DECLARE @SearchStartDate DATETIME = '30-JUN-2017'
DECLARE @SearchEndDate DATETIME = '15-MAY-2018'

DECLARE @Portfolio TABLE
(
    PortfolioId INT PRIMARY KEY IDENTITY(1,1),
    StartDate DATETIME,
    EndDate DATETIME
)

INSERT INTO @Portfolio
SELECT '01-JAN-2018',  '31-MAY-2018'
INSERT INTO @Portfolio
SELECT '01-JAN-2017',  '31-MAY-2018'


DECLARE @PortfolioComponents TABLE
(
    PortfolioComponentId INT PRIMARY KEY IDENTITY(1,1),
    PortfolioId INT, 
    SplitDate DATETIME
)
INSERT INTO @PortfolioComponents
SELECT 1, '28-FEB-2018'
INSERT INTO @PortfolioComponents
SELECT 1, '31-MAR-2018'

INSERT INTO @PortfolioComponents
SELECT 2, '31-MAR-2017'
INSERT INTO @PortfolioComponents
SELECT 2, '20-SEP-2017'
INSERT INTO @PortfolioComponents
SELECT 2, '15-JAN-2018'


SELECT * from @Portfolio
SELECT * from @PortfolioComponents

1 个答案:

答案 0 :(得分:1)

我相信我的结果接近我想要的结果,尽管不是

  • 最理想的方法
  • 从绩效角度看最佳方法
  • DECLARE @Temp TABLE (BenchmarkDate  Datetime, ComponentType int, PortfolioId INT)

    INSERT INTO @Temp SELECT StartDate , 1, PortfolioId FROM @Portfolio UNION SELECT EndDate , 2, PortfolioId FROM @Portfolio

    INSERT INTO @Temp SELECT SplitDate , 2, PortfolioId FROM @PortfolioComponents UNION SELECT SplitDate + 1 , 1, PortfolioId FROM @PortfolioComponents

    DECLARE @Results TABLE ( Id INT IDENTITY(1,1), StartDate DATETIME, EndDate DATETIME, PortfolioId INT )

    INSERT INTO @Results SELECT rset1.BenchmarkDate [Startdate], ( SELECT MIN(rset2.BenchmarkDate) FROM @Temp rset2 WHERE rset2.ComponentType = 2 AND rset2.BenchmarkDate > rset1.BenchmarkDate AND rset1.PortfolioId = rset2.PortfolioId) [Enddate], rset1.PortfolioId FROM @Temp rset1

    WHERE rset1.ComponentType = 1 ORDER BY rset1.PortfolioId, rset1.BenchmarkDate

    SELECT CASE WHEN (@SearchStartDate BETWEEN StartDate AND EndDate ) THEN @SearchStartDate ELSE StartDate END StartDate, CASE WHEN (@SearchEndDate BETWEEN StartDate AND EndDate) THEN @SearchEndDate ELSE EndDate END EndDate, PortfolioId , ( SELECT PortfolioComponentId FROM @PortfolioComponents pc WHERE (pc.PortfolioID = r.PortfolioId AND (DATEADD(d, 1, pc.SplitDate) = r.StartDate )) ) PortfolioComponentId FROM @Results r WHERE (@SearchStartDate < StartDate AND @SearchStartDate < EndDate AND @SearchEndDate > EndDate) OR (@SearchEndDate BETWEEN StartDate AND EndDate) OR (@SearchStartDate BETWEEN StartDate AND EndDate )