5

我有一张表格,列出了一年中的每个日期。每行还包含一个从 1 到 13 的期间编号,每年循环。它看起来像这样:

|        Date         | Period |
| 2012-12-27 00:00:00 |   12   |
| 2012-12-28 00:00:00 |   12   |
| 2012-12-29 00:00:00 |   13   |
| 2012-12-30 00:00:00 |   13   |
| 2012-12-31 00:00:00 |   13   |
| 2013-01-01 00:00:00 |   13   |
| 2013-01-02 00:00:00 |   13   |
|        . . .        |   13   | 
| 2013-02-10 00:00:00 |   01   |
|        . . .        |   01   | 
| 2013-03-14 00:00:00 |   02   |
|        . . .        |   02   | 
| 2013-05-05 00:00:00 |   03   |

正如您在上面看到的,第 13 期从 2012 年 12 月 29 日开始,到 2013 年 2 月 9 日结束。我通过获取第 13 期的第一个和最后一个日期来解决这个问题。

我需要编写一个查询来获取当前期间的期间开始和结束日期。但我遇到了问题,因为这些时期有时一年发生两次,有时像这个例子一样在年份之间重叠。

再举几个例子:

如果 getDate() = '2013-02-25 13:45:00' 则期间应为 01,开始和结束日期为 '2013-02-10 00:00:00' 和 '2013-03-14 00:00:00'

如果 getDate() = '2013-03-15 00:00:00' 那么时间段应该是 02 并且开始和结束日期应该是 '2013-03-14 00:00:00' 和 '2013-05-05 00:00:00'

我真的希望这是有道理的。让我知道是否需要澄清它!谢谢你的帮助 :)

4

5 回答 5

4

如果您使用的是 SQL Server 2012,您将为此使用lagor lead。相反,我将使用相关子查询:

select min(period) as period, MIN(date), MAX(date)
from (select t.*,
             (select min(date) from t t2 where t2.period <> t.period and t2.date > t.date) as nextp
      from t
     ) t
group by nextp

内部子查询获取下一个周期的日期。这对于具有相同期间记录的连续记录是相同的。然后我可以使用它进行分组。

于 2013-01-04T14:29:12.783 回答
3

两个递归 cte,在一段时间内查找开始日期和结束日期。

with CStart as
(
  select Date,
         Period
  from DateTable
  where Date = cast(getdate() as date)
  union all
  select D.Date,
         D.Period
  from DateTable as D
    inner join CStart
      on dateadd(day, -1, CStart.Date) = D.Date and
         CStart.Period = D.Period
),
CEnd as
(
  select Date,
         Period
  from DateTable
  where Date = cast(getdate() as date)
  union all
  select D.Date,
         D.Period
  from DateTable as D
    inner join CEnd
      on dateadd(day, 1, CEnd.Date) = D.Date and
         CEnd.Period = D.Period
),
CPeriod as
(
  select Period
  from DateTable
  where Date = cast(getdate() as date)
)
select Period,
       (select min(Date) from CStart) as StartDate,
       (select max(Date) from CEnd) as EndDate 
from CPeriod

SE 数据进行测试

于 2013-01-04T14:42:33.850 回答
1

试试这个代码

DECLARE @TODAYSPERIOD AS VARCHAR(2)

SET @TODAYSPERIOD = (SELECT PERIOD FROM MYTABLE
                    WHERE DATE = (DATEADD(D, DATEDIFF(D, 0, GETDATE()), 0)))

SELECT MAX(DATE), MIN(DATE), @TODAYSPERIOD FROM MYTABLE
WHERE PERIOD = @TODAYSPERIOD AND DATE BETWEEN ((DATEADD(D, DATEDIFF(D, 0, GETDATE()), 0)) - 45) AND ((DATEADD(D, DATEDIFF(D, 0, GETDATE()), 0)) + 45)

本质上,我们正在使用您的表(在上面的代码中,它被称为“MYTABLE”)来查找期间,然后只取 45 天半径内的日期(当前日期之前和之后),它被列为与今天相同的时期。

希望这可以帮助!

于 2013-01-04T14:44:59.963 回答
0

如果 - 且仅当- 表中不存在日期间隔并且每个日期恰好有一行,则可以使用此:

; WITH cte AS
  ( SELECT
        a.Date AS StartDate
      , b.Date AS EndDate
      , a.Period
      , ROW_NUMBER() OVER (ORDER BY a.Date) AS rn
    FROM tableX AS a
      LEFT JOIN tableX AS b
        ON  DATEADD(day, -1, a.Date) = b.Date
    WHERE a.Period <> b.Period 
       OR b.Date IS NULL 
  )
SELECT
    a.StartDate
  , COALESCE(b.EndDate, (SELECT MAX(Date) FROM tableX)) AS EndDate
  , a.Period
FROM
    cte AS a
  LEFT JOIN 
    cte AS b
      ON a.rn + 1 = b.rn ;

SQL-Fiddle中测试

于 2013-01-04T15:37:01.780 回答
0

你可以试试(在我的测试数据中,56是给定时间段内的最大天数)

SELECT A.period
     , MIN( B.date )
     , MAX( B.date )
  FROM dates A
 INNER JOIN dates B
    ON A.date >= DATEADD( dd, -56, B.date )
   AND A.date <= DATEADD( dd, 56, B.date )
   AND A.period = B.period 
 GROUP BY A.period
于 2013-01-04T14:50:33.777 回答