Sql 需要从单个生效日期计算开始和结束日期
我正在尝试编写SQL,从一个名为“生效日期”的日期计算每个项目的开始日期和结束日期。下面是我的数据的外观。有时某个项目的最后一个生效日期将是过去的,因此我希望该项目的结束日期是从今天开始的一年。表示例中的其他两项具有将来的生效日期,因此无需创建从今天开始的一年的日期和结束日期 我尝试过几种方法,但总是遇到不好的数据。下面是我的查询和错误结果的示例Sql 需要从单个生效日期计算开始和结束日期,sql,date,Sql,Date,我正在尝试编写SQL,从一个名为“生效日期”的日期计算每个项目的开始日期和结束日期。下面是我的数据的外观。有时某个项目的最后一个生效日期将是过去的,因此我希望该项目的结束日期是从今天开始的一年。表示例中的其他两项具有将来的生效日期,因此无需创建从今天开始的一年的日期和结束日期 我尝试过几种方法,但总是遇到不好的数据。下面是我的查询和错误结果的示例 select distinct tb1.itemid,tb1.EffectiveDate as startdate , case when date
select distinct tb1.itemid,tb1.EffectiveDate as startdate
, case
when dateadd(d,-1,tb2.EffectiveDate) < getdate()
or tb2.EffectiveDate is null
then getdate() +365
else dateadd(d,-1,tb2.EffectiveDate)
end as enddate
from #test tb1
left join #test as tb2 on (tb2.EffectiveDate > tb1.EffectiveDate
or tb2.effectivedate is null) and tb2.itemid = tb1.itemid
left join #test tb3 on (tb1.EffectiveDate < tb3.EffectiveDate
andtb3.EffectiveDate <tb2.EffectiveDate or tb2.effectivedate is null)
and tb1.itemid = tb3.itemid
left join #test tb4 on tb1.effectivedate = tb4.effectivedate \
and tb1.itemid = tb4.itemid
where tb1.itemID in (62741,62740, 65350)
结果-62740有一个额外的行
我希望看到下面的内容,因为前两个项目有一个未来的结束日期,不需要创建今天+365的结束日期,但最后一个项目只有一个生效日期,因此我们必须计算结束日期
我想我没看错你的问题。如果你能提供你的预期输出,这将有很大帮助 测试数据
CREATE TABLE #TestData (itemID int, EffectiveDate date)
INSERT INTO #TestData (itemID, EffectiveDate)
VALUES
(62741,'2016-06-25')
,(62741,'2016-06-04')
,(62740,'2016-07-09')
,(62740,'2016-06-25')
,(62740,'2016-06-04')
,(65350,'2016-05-28')
质疑
结果
itemID StartDate EndDate
62740 2016-06-04 2016-07-09
62741 2016-06-04 2016-06-25
65350 2016-05-28 2017-06-24
当语句..时,应使用case。。 [由于对需求的误解而导致错误的查询] 质疑 这应该做到:
SELECT itemid
,effective_date AS "Start"
,(SELECT MIN(effective_date)
FROM effective_date_tbl
WHERE effective_date > edt.effective_date
AND itemid = edt.itemid) AS "End"
FROM effective_date_tbl edt
WHERE effective_date <
(SELECT MAX(effective_date) FROM effective_date_tbl WHERE itemid = edt.itemid)
UNION ALL
SELECT itemid
,effective_date AS "Start"
,(SYSDATE + 365) AS "End"
FROM effective_date_tbl edt
WHERE 1 = ( SELECT COUNT(*) FROM effective_date_table WHERE itemid = edt.itemid )
ORDER BY 1, 2, 3;
我对表中具有多个EffectiveDate的项进行了此练习 您可以创建此视图
CREATE view [VW_TESTDATA]
AS ( SELECT * FROM
(SELECT ROW_NUMBER() OVER (ORDER BY Item,CONVERT(datetime,EffectiveDate,110)) AS ID, Item, DATA
FROM MyTable ) AS Q
)
因此,请使用select来比较相同的项目
select * from [VW_TESTDATA] as A inner join [VW_TESTDATA] as B on A.Item = B.Item and A.id = B.id-1
这样,你就永远可以进行次要和主要的约会
我不知道如何处理只有一个项目的日期,但这似乎是最简单的事情,可以使用UNION ALL添加到此查询中,因为该视图不包括单个项目
您还需要弄清楚如何处理两个有效日期相等的项目,您希望起始日期是多少?另外,请将表格复制到您的问题中。您能否提供一个示例,说明您希望从查询中获得的结果?下面的答案都是有效的,但我有一个问题,即当一个项目包含3个或更多条目时。假设一个ItemID有4个日期a、B、C、D。a>B、B>C、C>D或3行是理想的结果。您使用的是哪种DBMS?是的,但使用哪种DBMS?博士后?神谕DB2?SQL Server?结果中唯一的问题是它没有说明项目62740和生效日期2016年6月25日。您的日期2016年6月2日来自哪里?您提供的示例数据中没有这一点62740列出了3个生效日期,其中没有一个是2016年6月2日,也没有一个是2016年6月25日。不确定您看到的是2016年6月2日。@Joe我需要UNION ALL子句在1个生效日期处理此案件。对不起。。我误解了这个问题。。然而,我发现了一个非常可移植的解决方案,因为它不使用分区,而是支持一种索引规则,使项目的日期按时间顺序对应。移植性很明显,它与查询的diffucult部分、rownum机制和converrison相关,但这不是问题。我发送了一个版本,可以在查询中动态构建测试表,它可以在Sql FIDLE上进行测试。。该查询位于更新标记部分下的“应答时”字段中
SELECT
RESULT.ItemID AS ItemID,
DATE_FORMAT(RESULT.StartDate,'%m/%d/%Y') AS StartDate,
CASE WHEN RESULT.EndDate < CURRENT_DATE
THEN DATE_FORMAT((CURRENT_DATE + INTERVAL 365 DAY),'%m/%d/%Y')
ELSE DATE_FORMAT(RESULT.EndDate,'%m/%d/%Y')
END AS EndDate
FROM
(
SELECT
tabStartDate.ItemID AS ItemID,
tabStartDate.StartDate AS StartDate,
tabEndDate.EndDate
,tabStartDate.IDX,
tabEndDate.IDX AS IDX2
FROM
(
SELECT
tabStartDateIDX.ItemID AS ItemID,
tabStartDateIDX.EffectiveDate AS StartDate,
@rownum:=@rownum+1 AS IDX
FROM ITEMS AS tabStartDateIDX
ORDER BY tabStartDateIDX.ItemID, tabStartDateIDX.EffectiveDate
)AS tabStartDate
JOIN
(
SELECT
tabEndDateIDX.ItemID AS ItemID,
tabEndDateIDX.EffectiveDate AS EndDate,
@rownum:=@rownum+1 AS IDX
FROM ITEMS AS tabEndDateIDX
ORDER BY tabEndDateIDX.ItemID, tabEndDateIDX.EffectiveDate
)AS tabEndDate
ON tabStartDate.ItemID = tabEndDate.ItemID AND (tabEndDate.IDX - tabStartDate.IDX = ((select count(*) from ITEMS)+1) )
,(SELECT @rownum:=0) r
UNION
(
SELECT
tabStartDateSingleItem.ItemID AS ItemID,
tabStartDateSingleItem.EffectiveDate AS StartDate,
tabStartDateSingleItem.EffectiveDate AS EndDate
,0 AS IDX,0 AS IDX2
FROM ITEMS AS tabStartDateSingleItem
Group By tabStartDateSingleItem.ItemID
HAVING Count(tabStartDateSingleItem.ItemID) = 1
)
) AS RESULT
;
SELECT itemid
,effective_date AS "Start"
,(SELECT MIN(effective_date)
FROM effective_date_tbl
WHERE effective_date > edt.effective_date
AND itemid = edt.itemid) AS "End"
FROM effective_date_tbl edt
WHERE effective_date <
(SELECT MAX(effective_date) FROM effective_date_tbl WHERE itemid = edt.itemid)
UNION ALL
SELECT itemid
,effective_date AS "Start"
,(SYSDATE + 365) AS "End"
FROM effective_date_tbl edt
WHERE 1 = ( SELECT COUNT(*) FROM effective_date_table WHERE itemid = edt.itemid )
ORDER BY 1, 2, 3;
CREATE view [VW_TESTDATA]
AS ( SELECT * FROM
(SELECT ROW_NUMBER() OVER (ORDER BY Item,CONVERT(datetime,EffectiveDate,110)) AS ID, Item, DATA
FROM MyTable ) AS Q
)
select * from [VW_TESTDATA] as A inner join [VW_TESTDATA] as B on A.Item = B.Item and A.id = B.id-1