First commit, 已上架的電子書
This commit is contained in:
@@ -0,0 +1,130 @@
|
||||
這個 SQL Script 是針對 Jack 的飯店業 BI
|
||||
需要看到周變化,所以整理出來的 Script
|
||||
BI 一般是看趨勢,理論上不會看到這麼細,但是要做當然是可以的
|
||||
|
||||
|
||||
/*
|
||||
以年度共幾周為單位取日期區間(一年共 52 周)
|
||||
以下內容是 ChatGPT 的結果,令人驚豔
|
||||
|
||||
Michael 20250604
|
||||
*/
|
||||
|
||||
SET DATEFIRST 7; -- 設定週日為每週第一天
|
||||
|
||||
WITH Weeks AS (
|
||||
SELECT
|
||||
DATEADD(DAY, -(DATEPART(WEEKDAY, DATEFROMPARTS(2025, 1, 1)) - 1), DATEFROMPARTS(2025, 1, 1)) AS WeekStart
|
||||
UNION ALL
|
||||
SELECT
|
||||
DATEADD(WEEK, 1, WeekStart)
|
||||
FROM Weeks
|
||||
WHERE DATEADD(WEEK, 1, WeekStart) <= DATEFROMPARTS(2025, 12, 31)
|
||||
),
|
||||
WeeksWithMonth AS (
|
||||
SELECT
|
||||
ROW_NUMBER() OVER (ORDER BY WeekStart) AS WeekNumber,
|
||||
WeekStart,
|
||||
DATEADD(DAY, 6, WeekStart) AS EndDate,
|
||||
MONTH(WeekStart) AS MonthNumber,
|
||||
DATENAME(MONTH, WeekStart) AS MonthName,
|
||||
YEAR(WeekStart) AS YearNumber
|
||||
FROM Weeks
|
||||
WHERE YEAR(WeekStart) = 2025 OR YEAR(DATEADD(DAY, 6, WeekStart)) = 2025
|
||||
),
|
||||
WeeksWithMonthRank AS (
|
||||
SELECT *,
|
||||
ROW_NUMBER() OVER (PARTITION BY YearNumber, MonthNumber ORDER BY WeekStart) AS WeekOfMonth
|
||||
FROM WeeksWithMonth
|
||||
)
|
||||
SELECT
|
||||
WeekNumber,
|
||||
WeekStart AS StartDate,
|
||||
EndDate,
|
||||
MonthName,
|
||||
MonthNumber,
|
||||
WeekOfMonth -- ?? 當月第幾週
|
||||
-- into Year_WeekData
|
||||
FROM WeeksWithMonthRank
|
||||
ORDER BY StartDate
|
||||
OPTION (MAXRECURSION 100)
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/*
|
||||
以下的寫法會將跨月的周,拆成 2 筆
|
||||
目的是如果要以月為單位看第幾周,就用下面的語法
|
||||
*/
|
||||
|
||||
-- SET DATEFIRST 7; -- 設定週日為一週的第一天(星期日)
|
||||
SET DATEFIRST 1; -- 設定週一為一週的第一天(星期一)
|
||||
|
||||
-- 產生所有週的開始日
|
||||
WITH Weeks AS (
|
||||
SELECT
|
||||
DATEADD(DAY, -(DATEPART(WEEKDAY, DATEFROMPARTS(2025, 1, 1)) - 1), DATEFROMPARTS(2025, 1, 1)) AS WeekStart
|
||||
UNION ALL
|
||||
SELECT
|
||||
DATEADD(WEEK, 1, WeekStart)
|
||||
FROM Weeks
|
||||
WHERE DATEADD(WEEK, 1, WeekStart) <= DATEFROMPARTS(2025, 12, 31)
|
||||
),
|
||||
|
||||
-- 加上 WeekNumber(全年第幾週)
|
||||
WeeksWithNumber AS (
|
||||
SELECT
|
||||
ROW_NUMBER() OVER (ORDER BY WeekStart) AS WeekNumber,
|
||||
WeekStart,
|
||||
DATEADD(DAY, 6, WeekStart) AS WeekEnd
|
||||
FROM Weeks
|
||||
),
|
||||
|
||||
-- 將每週展開成7天
|
||||
DaysInWeek AS (
|
||||
SELECT
|
||||
W.WeekNumber,
|
||||
W.WeekStart,
|
||||
DATEADD(DAY, N.number, W.WeekStart) AS DayDate
|
||||
FROM WeeksWithNumber W
|
||||
JOIN master.dbo.spt_values N ON N.type = 'P' AND N.number BETWEEN 0 AND 6
|
||||
WHERE YEAR(DATEADD(DAY, N.number, W.WeekStart)) = 2025
|
||||
),
|
||||
|
||||
-- 拆分週中涉及的每個月份的起訖日
|
||||
WeekMonthSplit AS (
|
||||
SELECT
|
||||
WeekNumber,
|
||||
WeekStart,
|
||||
MONTH(DayDate) AS MonthNumber,
|
||||
DATENAME(MONTH, DayDate) AS MonthName,
|
||||
YEAR(DayDate) AS YearNumber,
|
||||
MIN(DayDate) AS StartDate,
|
||||
MAX(DayDate) AS EndDate
|
||||
FROM DaysInWeek
|
||||
GROUP BY WeekNumber, WeekStart, MONTH(DayDate), DATENAME(MONTH, DayDate), YEAR(DayDate)
|
||||
),
|
||||
|
||||
-- 加上「當月第幾週」
|
||||
FinalResult AS (
|
||||
SELECT *,
|
||||
ROW_NUMBER() OVER (PARTITION BY YearNumber, MonthNumber ORDER BY StartDate) AS WeekOfMonth
|
||||
FROM WeekMonthSplit
|
||||
)
|
||||
|
||||
-- 輸出最終結果
|
||||
SELECT
|
||||
ROW_NUMBER() OVER (ORDER BY StartDate) AS RecordID,
|
||||
WeekNumber,
|
||||
WeekStart,
|
||||
StartDate,
|
||||
EndDate,
|
||||
MonthName,
|
||||
MonthNumber,
|
||||
WeekOfMonth
|
||||
-- into Year_WeekData
|
||||
FROM FinalResult
|
||||
ORDER BY StartDate
|
||||
OPTION (MAXRECURSION 100)
|
||||
Reference in New Issue
Block a user