0

我是 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

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

    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
`
4

2 回答 2

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
于 2013-10-03T22:12:28.167 回答
0

您每天都在循环,但从不在日级别存储,因此您执行的 INSERT 次数是需要的 7 倍。在您的 INSERT 语句上方添加以下内容

IF DATEPART(weekday, CAST(CAST(@iStartYear * 10000 + @iMth * 100 + @iDay AS VARCHAR(8)) AS datetime)) = 1
INSERT INTO dim_period_week ...
于 2013-10-03T21:31:42.920 回答