(SQL Server 2008和以上):我需要更新dimDate
表包括以下幾列:SQL Server的日期表:編程找到的最後一個星期日在一個特定的月份
- 上週日的月份:
- 上週一月:
- 上週二月:
- 上週三每月的:
- 上週四月:
- 上週五的一個月:
- 上週六每月的:
不要誤會我的意思;這是非常簡單的,通過下面的代碼來定位該月的最後一天SQL:
CONVERT(DATE, DATEADD(DD, - (DATEPART(DD, (DATEADD(MM, 1, DayInTime)))), DATEADD(MM, 1, DayInTime))) AS [LastDayOfTheMonth]
但我找不到任何地方在互聯網上,我承認不花2個多小時搜尋,那裏的人們公開展示瞭如何月份的識別最後(插天名稱)。
因此,我解決了這個方程,我在這裏張貼,如果它是對別人有用,或者,如果任何人有一個更簡單的方法,我可以使用,但根本無法看到它。
的dimDates
表通過預先填充dimNumbers
表填充:
IF OBJECT_ID('dbo.dimNumbers') IS NOT NULL
DROP TABLE dbo.dimNumbers;
DECLARE @UpperBound INT = 1000000;
;WITH cteN(Number) AS
(
SELECT
ROW_NUMBER() OVER (ORDER BY s1.[object_id]) - 1
FROM
sys.all_columns AS s1
CROSS JOIN
sys.all_columns AS s2
)
SELECT [Number]
INTO ref.dimNumbers
FROM cteN
WHERE [Number] <= @UpperBound;
CREATE UNIQUE CLUSTERED INDEX CIX_dimNumbers ON ref.dimNumbers([Number]);
然後被填充昏暗日期表通過以下的手段。是的,我很懶,希望SQL執行所有可能的計算。
DECLARE @YearsToPopulate INT = 130;
-- Use the Magic of SQL to identify 1 Jan and then 31st December at the various edges of the required date time frames.
DECLARE @StartDate DATE = DATEADD(yy, DATEDIFF(yy,0,DATEADD(yyyy,[email protected],GETDATE())), 0);
DECLARE @EndDate DATE = DATEADD(yy, DATEDIFF(yy,0,DATEADD(yyyy,@YearsToPopulate,GETDATE())) + 1, -1);
DECLARE @RecordsToCreate INT = DATEDIFF(dd,@StartDate,@EndDate);
;WITH MyFullDateRange AS
(
SELECT TOP (@RecordsToCreate)
CAST(DATEADD(dd, Number, @StartDate) AS DATE) AS DayInTime
FROM
ref.[dimNumbers]
)
SELECT
--Insert Formulas here, using [DayInTime] as the Variable
-- The Formulas I have used here are not the topic of this discussion.
FROM
MyFullDateRange
所以,我花了幾個小時來證明,但我終於想出了一個簡單的,可重複的方式來發現「最後一個月(插天名稱)」。
NB:將上述SELECT
語句內以下。
--Sunday [DayOfWeek] = 1.. Need to convert 1 to 0 <-> N + (7 - 1) % 7
DATEADD(DD,
- ((DATEPART(dw, DATEADD(DD, - (DATEPART(DD, (DATEADD(MM, 1, DayInTime)))), DATEADD(MM, 1, DayInTime)))) + (7 - 1)) % 7 ,
CONVERT(DATE, DATEADD(DD, - (DATEPART(DD, (DATEADD(MM, 1, DayInTime)))), DATEADD(MM, 1, DayInTime)))
)
AS [LastsSundayOfTheMonth]
--Monday [DayOfWeek] = 2.. Need to convert 2 to 0 <-> N + (7 - 2) % 7
DATEADD(DD,
- ((DATEPART(dw, DATEADD(DD, - (DATEPART(DD, (DATEADD(MM, 1, DayInTime)))), DATEADD(MM, 1, DayInTime)))) + (7 - 2)) % 7 ,
CONVERT(DATE, DATEADD(DD, - (DATEPART(DD, (DATEADD(MM, 1, DayInTime)))), DATEADD(MM, 1, DayInTime)))
)
AS [LastMondayOfTheMonth]
--Tuesday [DayOfWeek] = 3.. Need to convert 3 to 0 <-> N + (7 - 3) % 7
DATEADD(DD,
- ((DATEPART(dw, DATEADD(DD, - (DATEPART(DD, (DATEADD(MM, 1, DayInTime)))), DATEADD(MM, 1, DayInTime)))) + (7 -3)) % 7 ,
CONVERT(DATE, DATEADD(DD, - (DATEPART(DD, (DATEADD(MM, 1, DayInTime)))), DATEADD(MM, 1, DayInTime)))
)
AS [LastTuesdayOfTheMonth]
--Wednesday [DayOfWeek] = 4.. Need to convert 4 to 0 <-> N + (7 - 4) % 7
DATEADD(DD,
- ((DATEPART(dw, DATEADD(DD, - (DATEPART(DD, (DATEADD(MM, 1, DayInTime)))), DATEADD(MM, 1, DayInTime)))) + (7 - 4)) % 7 ,
CONVERT(DATE, DATEADD(DD, - (DATEPART(DD, (DATEADD(MM, 1, DayInTime)))), DATEADD(MM, 1, DayInTime)))
)
AS [LastWednesdayOfTheMonth]
--Thursday [DayOfWeek] = 5.. Need to convert 5 to 0 <-> N + (7 - 5) % 7
DATEADD(DD,
- ((DATEPART(dw, DATEADD(DD, - (DATEPART(DD, (DATEADD(MM, 1, DayInTime)))), DATEADD(MM, 1, DayInTime)))) + (7 - 5)) % 7 ,
CONVERT(DATE, DATEADD(DD, - (DATEPART(DD, (DATEADD(MM, 1, DayInTime)))), DATEADD(MM, 1, DayInTime)))
)
AS [LastThursdayOfTheMonth]
--Friday [DayOfWeek] = 6.. Need to convert 6 to 0 <-> N + (7 - 6) % 7
DATEADD(DD,
- ((DATEPART(dw, DATEADD(DD, - (DATEPART(DD, (DATEADD(MM, 1, DayInTime)))), DATEADD(MM, 1, DayInTime)))) + (7-6)) % 7 ,
CONVERT(DATE, DATEADD(DD, - (DATEPART(DD, (DATEADD(MM, 1, DayInTime)))), DATEADD(MM, 1, DayInTime)))
)
AS [LastFridayOfTheMonth]
--Saturday [DayOfWeek] = 7.. Need to convert 7 to 0 <-> N + (7 - 7) % 7
DATEADD(DD,
- ((DATEPART(dw, DATEADD(DD, - (DATEPART(DD, (DATEADD(MM, 1, DayInTime)))), DATEADD(MM, 1, DayInTime)))) + (7-7)) % 7 ,
CONVERT(DATE, DATEADD(DD, - (DATEPART(DD, (DATEADD(MM, 1, DayInTime)))), DATEADD(MM, 1, DayInTime)))
)
AS [LastsSaturdayOfTheMonth]
我希望這對他人有用,或者有人能夠指出一個更簡單的方法來執行這些操作。
要在[馬茨]答擴大爲SQL Server 2012:
下面的代碼適用於SQL Server 2012的及以上,並希望清楚地標識的每一天是如何識別。 (如果不是,讓我知道,我會澄清)
DECLARE @YearsToPopulate INT = 130;
-- Use the Magic of SQL to identify 1 Jan and then 31st December at the various edges of the required date time frames.
DECLARE @Date1 DATE = DATEADD(yy, DATEDIFF(yy,0,DATEADD(yyyy,[email protected],GETDATE())), 0);
DECLARE @Date2 DATE = DATEADD(yy, DATEDIFF(yy,0,DATEADD(yyyy,@YearsToPopulate,GETDATE())) + 1, -1);
DECLARE @RecordsToCreate INT = DATEDIFF(dd,@Date1,@Date2);
WITH MyFullDateRange AS
(
SELECT TOP (@RecordsToCreate) CAST(DATEADD(dd, Number, @Date1) AS DATE) AS DayInTime
FROM ref.[dimNumbers]
)
SELECT DayInTime
--Sunday [DayOfWeek] = 1.. Need to convert 1 to 0 <-> N + (0 - 1) % 7
,LastSundayOfMonth = DATEADD(DAY, 0 - (@@DATEFIRST - 1 + DATEPART(dw,EOMONTH(DayInTime))) % 7, EOMONTH(DayInTime))
--Monday [DayOfWeek] = 2.. Need to convert 2 to 0 <-> N + (0 - 2) % 7
,LastMondayOfMonth = DATEADD(DAY, 0 - (@@DATEFIRST - 2 + DATEPART(dw,EOMONTH(DayInTime))) % 7, EOMONTH(DayInTime))
--Tuesday [DayOfWeek] = 3.. Need to convert 2 to 0 <-> N + (0 - 3) % 7
,LastTuesdayOfMonth = DATEADD(DAY, 0 - (@@DATEFIRST - 3 + DATEPART(dw,EOMONTH(DayInTime))) % 7, EOMONTH(DayInTime))
--Wednesday [DayOfWeek] = 4.. Need to convert 4 to 0 <-> N + (0 - 4) % 7
,LastWednesdayOfMonth = DATEADD(DAY, 0 - (@@DATEFIRST - 4 + DATEPART(dw,EOMONTH(DayInTime))) % 7, EOMONTH(DayInTime))
--Thursday [DayOfWeek] = 5.. Need to convert 2 to 0 <-> N + (0 - 5) % 7
,LastThursdayOfMonth = DATEADD(DAY, 0 - (@@DATEFIRST - 5 + DATEPART(dw,EOMONTH(DayInTime))) % 7, EOMONTH(DayInTime))
--Friday [DayOfWeek] = 6.. Need to convert 2 to 0 <-> N + (0 - 6) % 7
,LastFridayOfMonth = DATEADD(DAY, 0 - (@@DATEFIRST - 6 + DATEPART(dw,EOMONTH(DayInTime))) % 7, EOMONTH(DayInTime))
--Saturday [DayOfWeek] = 7.. Need to convert 2 to 0 <-> N + (0 - 7) % 7
,LastSaturdayOfMonth = DATEADD(DAY, 0 - (@@DATEFIRST - 7 + DATEPART(dw,EOMONTH(DayInTime))) % 7, EOMONTH(DayInTime))
FROM MyFullDateRange;
我將通過這個代碼,如果我沒有到支持SQL Server 2008
更多的SQL Server 2012開始碼:
不幸的是,我希望會是一個很好的選擇,是行不通的。請記住該解決方案需要適合dimDate表格。任何建議,以改善這一點?我不喜歡這種解決方案的一部分,我需要執行雙重前往dimDate表進行更新。
DECLARE @YearsToPopulate INT = 130;
DECLARE @Date1 DATE = DATEADD(yy, DATEDIFF(yy,0,DATEADD(yyyy,[email protected],GETDATE())), 0);
DECLARE @Date2 DATE = DATEADD(yy, DATEDIFF(yy,0,DATEADD(yyyy,@YearsToPopulate,GETDATE())) + 1, -1);
DECLARE @RecordsToCreate INT = DATEDIFF(dd,@Date1,@Date2);
WITH MyFullDateRange AS
(
SELECT TOP (@RecordsToCreate) CAST(DATEADD(dd, Number, @Date1) AS DATE) AS DayInTime
FROM ref.[dimNumbers]
)
, CreateListOfDatesAndDOWs As
(
Select DayInTime AS DayInTime, DatePART(DW , DayInTime) AS DayNumber
From MyFullDateRange
)
Select DayInTime AS [currentDate]--SQL 2012 -- DateFromParts(Year(DayInTime),Month(DayInTime) , 1) AS [currentDate]
,LastSun = MAX(CASE WHEN DayNumber=1 THEN DayInTime END)
,LastMon = MAX(CASE WHEN DayNumber=2 THEN DayInTime END)
,LastTue = MAX(CASE WHEN DayNumber=3 THEN DayInTime END)
,LastWed = MAX(CASE WHEN DayNumber=4 THEN DayInTime END)
,LastThu = MAX(CASE WHEN DayNumber=5 THEN DayInTime END)
,LastFri = MAX(CASE WHEN DayNumber=6 THEN DayInTime END)
,LastSat = MAX(CASE WHEN DayNumber=7 THEN DayInTime END)
From CreateListOfDatesAndDOWs
Group By DayInTime --DateFromParts(Year(DayInTime),Month(DayInTime),1)--SQL 2012
因爲這將返回下面的結果集,該結果集對於dimDate表而言並不是我們所追求的。 (我需要弄清楚如何格式化表!)SQL服務器2012+
DATEADD(DAY, 0 - (@@DATEFIRST - 1 + DATEPART(dw,EOMONTH(DateCol))) % 7, EOMONTH(DateCol))
這個公式將工作無論什麼DATEFIRST
值設置(因爲使用EOMONTH()
的)
currentDate LastSun LastMon LastTue LastWed LastThu LastFri LastSat
----------- ---------- ---------- ---------- ---------- ---------- ---------- ----------
1886-01-01 NULL NULL NULL NULL NULL 1886-01-01 NULL
1886-01-02 NULL NULL NULL NULL NULL NULL 1886-01-02
1886-01-03 1886-01-03 NULL NULL NULL NULL NULL NULL
1886-01-04 NULL 1886-01-04 NULL NULL NULL NULL NULL
1886-01-05 NULL NULL 1886-01-05 NULL NULL NULL NULL
1886-01-06 NULL NULL NULL 1886-01-06 NULL NULL NULL
1886-01-07 NULL NULL NULL NULL 1886-01-07 NULL NULL
1886-01-08 NULL NULL NULL NULL NULL 1886-01-08 NULL
1886-01-09 NULL NULL NULL NULL NULL NULL 1886-01-09
1886-01-10 1886-01-10 NULL NULL NULL NULL NULL NULL
1886-01-11 NULL 1886-01-11 NULL NULL NULL NULL NULL
1886-01-12 NULL NULL 1886-01-12 NULL NULL NULL NULL
1886-01-13 NULL NULL NULL 1886-01-13 NULL NULL NULL
1886-01-14 NULL NULL NULL NULL 1886-01-14 NULL NULL
1886-01-15 NULL NULL NULL NULL NULL 1886-01-15 NULL
1886-01-16 NULL NULL NULL NULL NULL NULL 1886-01-16
1886-01-17 1886-01-17 NULL NULL NULL NULL NULL NULL
1886-01-18 NULL 1886-01-18 NULL NULL NULL NULL NULL
1886-01-19 NULL NULL 1886-01-19 NULL NULL NULL NULL
1886-01-20 NULL NULL NULL 1886-01-20 NULL NULL NULL
1886-01-21 NULL NULL NULL NULL 1886-01-21 NULL NULL
1886-01-22 NULL NULL NULL NULL NULL 1886-01-22 NULL
1886-01-23 NULL NULL NULL NULL NULL NULL 1886-01-23
1886-01-24 1886-01-24 NULL NULL NULL NULL NULL NULL
1886-01-25 NULL 1886-01-25 NULL NULL NULL NULL NULL
1886-01-26 NULL NULL 1886-01-26 NULL NULL NULL NULL
1886-01-27 NULL NULL NULL 1886-01-27 NULL NULL NULL
1886-01-28 NULL NULL NULL NULL 1886-01-28 NULL NULL
1886-01-29 NULL NULL NULL NULL NULL 1886-01-29 NULL
1886-01-30 NULL NULL NULL NULL NULL NULL 1886-01-30
1886-01-31 1886-01-31 NULL NULL NULL NULL NULL NULL
1886-02-01 NULL 1886-02-01 NULL NULL NULL NULL NULL
1886-02-02 NULL NULL 1886-02-02 NULL NULL NULL NULL
1886-02-03 NULL NULL NULL 1886-02-03 NULL NULL NULL
1886-02-04 NULL NULL NULL NULL 1886-02-04 NULL NULL
1886-02-05 NULL NULL NULL NULL NULL 1886-02-05 NULL
1886-02-06 NULL NULL NULL NULL NULL NULL 1886-02-06
請標記你的DBMS以及版本。 –