Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/date/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Sql 需要从单个生效日期计算开始和结束日期_Sql_Date - Fatal编程技术网

Sql 需要从单个生效日期计算开始和结束日期

Sql 需要从单个生效日期计算开始和结束日期,sql,date,Sql,Date,我正在尝试编写SQL,从一个名为“生效日期”的日期计算每个项目的开始日期和结束日期。下面是我的数据的外观。有时某个项目的最后一个生效日期将是过去的,因此我希望该项目的结束日期是从今天开始的一年。表示例中的其他两项具有将来的生效日期,因此无需创建从今天开始的一年的日期和结束日期 我尝试过几种方法,但总是遇到不好的数据。下面是我的查询和错误结果的示例 select distinct tb1.itemid,tb1.EffectiveDate as startdate , case when date

我正在尝试编写SQL,从一个名为“生效日期”的日期计算每个项目的开始日期和结束日期。下面是我的数据的外观。有时某个项目的最后一个生效日期将是过去的,因此我希望该项目的结束日期是从今天开始的一年。表示例中的其他两项具有将来的生效日期,因此无需创建从今天开始的一年的日期和结束日期

我尝试过几种方法,但总是遇到不好的数据。下面是我的查询和错误结果的示例

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