循环日期并返回周sql

时间:2013-09-24 07:38:03

标签: sql sql-server tsql date loops

我是SQL的新手(仅在3天后开始),我遇到了一个问题,希望有人能够帮助我。

我有一个创建日期循环的查询,根据传入的日期返回周数。这里的想法是通过几天,几个月和几年的循环,并返回一周的价值。但由于这些原因,我得到了相同结果的多个条目。

例如。我得到了:

period_wk_key   period_yr_key  period_week  period_week_day  period_week_full_desc
--------------- -------------- ------------ --------------   -----------------------
200001          2000           1             6               2000 WEEK 1
200001          2000           1             6               2000 WEEK 1
200001          2000           1             6               2000 WEEK 1
.               .              .             .               .
200002          2000           2             6               2000 WEEK 2
200002          2000           2             6               2000 WEEK 2
200002          2000           2             6               2000 WEEK 2
.               .              .             .               .    
200003          2000           3             6               2000 WEEK 3

每个period_wk_key都会返回7个类似的行,这不是我想要的。

理想的情况应该是:

period_wk_key   period_yr_key  period_week  period_week_day  period_week_full_desc
--------------- -------------- ------------ --------------   -----------------------
200001          2000           1             6               2000 WEEK 1
200002          2000           2             6               2000 WEEK 2
200003          2000           3             6               2000 WEEK 3
200004          2000           4             6               2000 WEEK 4

我需要知道一种限制循环输出数量的方法,这样我就可以拥有不同的记录而不是多个相似的行。我在下面附上了一个代码。它可能是你们许多人的废话,但这只是我开始编写脚本的第3天。非常感谢任何帮助。

    DECLARE @iStartYear INT 
    SET @iStartYear = 2000  
    DECLARE @iEndYear INT
    SET @iEndYear = 2030
    DECLARE @iMth INT
    SET @iMth = 1
    DECLARE @iDay INT
    SET @iDay = 1
    DECLARE @iWeek INT

`DECLARE @StartDate DATETIME
WHILE (@iStartYear <= @iEndYear)
   BEGIN
      WHILE (@iMth <= 12)
         BEGIN
      WHILE (@iDay <= DATEDIFF(DAY,DATEADD(DAY, 0, DATEADD(m, ((@iStartYear - 1900) * 12) + @iMth - 1, 0)),DATEADD(DAY, 0, DATEADD(m, ((@iStartYear - 1900) * 12) + @iMth, 0)))))
              BEGIN `

    SET @iWeek = (DATEPART(dy, CONVERT(DATETIME, CONVERT(VARCHAR(4), @iStartYear) + '/' + CONVERT(VARCHAR(2), @iMth) + '/' + CONVERT(VARCHAR(2), @iDay))) - 1) / 7 + 1;

    INSERT INTO dim_period_week (period_wk_key, period_yr_key, period_week, period_week_full_desc,start_date, end_date, period_week_day)
    VALUES (    
    (SELECT CASE WHEN @iWeek < 10 THEN 
        CAST((@iStartYear) AS VARCHAR) + '0' + CAST((@iWeek) AS VARCHAR)
    ELSE
        CAST((@iStartYear) AS VARCHAR)+ CAST((@iWeek) AS VARCHAR)
    END),           
    @iStartYear,
    (SELECT (DATEPART(dy, CONVERT(DATETIME, CONVERT(VARCHAR(4), @iStartYear) + '/' + CONVERT(VARCHAR(2), @iMth) + '/' + CONVERT(VARCHAR(2), @iDay))) - 1) / 7 + 1),

    (SELECT CAST((@iStartYear) AS VARCHAR) + ' ' + 'WEEK' + ' ' + CAST((@iWeek) AS VARCHAR)),
    (SELECT DATEADD(wk,@iWeek-1, DATEADD(yy,@iStartYear-1900,0))), --START DATE
    (SELECT DATEADD(wk,@iWeek, DATEADD(yy,@iStartYear-1900,0)) -1), --END DATE
    (SELECT DATEDIFF(DAY, DATEADD(wk,@iWeek-1, DATEADD(yy,@iStartYear-1900,0)), DATEADD(wk,@iWeek, DATEADD(yy,@iStartYear-1900,0)) -1))
)                           
    `SET @iDay = @iDay + 1 
    END             
    SET @iDay = 1
    SET @iMth = @iMth + 1
    END
    SET @iMth = 1
    SET @iStartYear = @iStartYear + 1
    END
`

2 个答案:

答案 0 :(得分:0)

您每天都在进行循环,但从不在日期级别进行存储,因此您根据需要进行了7次INSERT。在INSERT语句上方添加以下内容

IF DATEPART(weekday, CAST(CAST(@iStartYear * 10000 + @iMth * 100 + @iDay AS VARCHAR(8)) AS datetime)) = 1
INSERT INTO dim_period_week ...

答案 1 :(得分:0)

以下是使用数字表的基于集合的方法。

IF OBJECT_ID('tempdb.dbo.#Numbers') IS NOT NULL DROP TABLE #Numbers
GO
DECLARE @startDate DATETIME = '20000101'
SELECT 
    (a.Number * 256) + b.Number AS Number
INTO #Numbers
FROM 
    (SELECT number FROM master..spt_values WHERE type = 'P' AND number <= 255) a (Number),
    (SELECT number FROM master..spt_values WHERE type = 'P' AND number <= 255) b (Number)
WHERE 
  (a.Number * 256) + b.Number BETWEEN 0 AND 1617

SELECT 
  WeekKey   = CAST(YEAR(DATEADD(day, N.Number * 7, @startDate)) * 100 + DATEPART(week, DATEADD(day, N.Number * 7, @startDate)) AS VARCHAR(10)),
  TheYear   = YEAR(DATEADD(day, N.Number * 7, @startDate)),
  TheWeek   = DATEPART(week, DATEADD(day, N.Number * 7, @startDate)),
  TheWeekDay= DATEPART(weekday, DATEADD(day, N.Number * 7, @startDate)),
  WeekDetail= DATENAME(year, DATEADD(day, N.Number * 7, @startDate)) + ' WEEK ' + DATENAME(week, DATEADD(day, N.Number * 7, @startDate)),
  StartDate = DATEADD(day, N.Number * 7, @startDate),
  EndDate   = DATEADD(day, 6, DATEADD(day, N.Number * 7, @startDate))
FROM #Numbers N 
ORDER BY 1