将行中的日期时间轴转换为sql server中的列式格式

时间:2015-08-07 17:39:36

标签: sql-server date datetime

我的数据如下:

SKU      StartDateTime  EndDateTime
es311335    6/30/2013   5/24/2015
es311355    6/30/2013   6/28/2015
es311470    6/30/2013   12/14/2014
es311478    6/30/2013   6/28/2015
es311501    6/30/2013   6/28/2015
es311574    6/30/2013   6/28/2015
es311632    6/30/2013   6/22/2014

我希望它的格式为:

SKU         Date
es311335    6/30/2013
es311335    7/7/2013
es311335    7/14/2013
es311335    7/21/2013
es311335    7/28/2013
es311335    8/4/2013
------      ------
es311335    24/05/2014

我使用了以下查询,但这并没有给我正确的结果。

DECLARE @Interval NVARCHAR(10), @I DATETIME, 
@IntervalMin DATETIME, @IntervalMax DATETIME

--- Set Interval DAY or MONTH or YEAR -----------------

SET @Interval = 'DAY' 

-------------------------------------------------------

DECLARE @Records TABLE
(StartDateTime DATETIME
 ,EndDateTime DATETIME)

INSERT INTO @Records
SELECT StartDateTime, EndDateTime
From records

DECLARE @Results TABLE
(StartDate DATETIME
 ,EndDate DATETIME)

WHILE EXISTS(SELECT * FROM @Records)
BEGIN
  SELECT TOP 1 @IntervalMin = startdatetime, @IntervalMax = enddatetime
  FROM @Records

  SET @I = @IntervalMin

  WHILE (@I <= @IntervalMax)
  BEGIN
    IF @Interval = 'DAY'
    BEGIN
      INSERT INTO @Results
      SELECT @I, CASE WHEN CONVERT(DATE, DATEADD(DAY, 7, @I)) > @IntervalMax 
          THEN @IntervalMax ELSE CONVERT(DATE, DATEADD(DAY, 7, @I)) END

      SET @I = CONVERT(DATE, DATEADD(DAY, 7, @I))
    END
END

  DELETE FROM @Records 
  WHERE startdatetime = @IntervalMin 
  AND enddatetime = @IntervalMax
END

SELECT *
FROM @Results

1 个答案:

答案 0 :(得分:0)

我在评论中提到你应该使用计数表。这是我的计数表版本。我把它作为我系统中的一个视图,所以我不必永久地存储它,它会产生10,000行,读数为零。

create View [dbo].[cteTally] as

WITH
    E1(N) AS (select 1 from (values (1),(1),(1),(1),(1),(1),(1),(1),(1),(1))dt(n)),
    E2(N) AS (SELECT 1 FROM E1 a, E1 b), --10E+2 or 100 rows
    E4(N) AS (SELECT 1 FROM E2 a, E2 b), --10E+4 or 10,000 rows max
    cteTally(N) AS 
    (
        SELECT  ROW_NUMBER() OVER (ORDER BY (SELECT NULL)) FROM E4
    )
select N from cteTally

现在这又如何适用于你想要做的事情?我们可以使用一些日期数学来将计数表合并到一个基于集合的解决方案中,而不是RBAR(通过痛苦的行排)循环结构。在我们找到解决方案之前,我们必须以其他人可以使用的格式构建数据。

这是一种方法。

if OBJECT_ID('tempdb..#Something') is not null
    drop table #Something

create table #Something
(
    SKU char(9)
    , StartDateTime datetime
    , EndDateTime datetime
)

insert #Something
select 'es311335', '6/30/2013', '5/24/2015' union all
select 'es311355', '6/30/2013', '6/28/2015' union all
select 'es311470', '6/30/2013', '12/14/2014' union all
select 'es311478', '6/30/2013', '6/28/2015' union all
select 'es311501', '6/30/2013', '6/28/2015' union all
select 'es311574', '6/30/2013', '6/28/2015' union all
select 'es311632', '6/30/2013', '6/22/2014'

好酷。现在我们有一个计数表和一些数据可供使用。让我们看看当我们使用计数表时这是多么简单。

select s.*
    , DATEADD(week, N - 1, StartDateTime)
from #Something s
join cteTally t on t.N <= DATEDIFF(week, StartDateTime, EndDateTime) + 1
order by SKU, DATEADD(week, N - 1, StartDateTime)