📅 Why You Should Create a Permanent Calendar Table in SQL Server

Creating a permanent calendar table (also known as a date dimension) is a best practice for production systems that involve reporting, scheduling, or time-based analytics. It simplifies logic, improves performance, and makes queries more readable.


🧱 What Is a Calendar Table?

A calendar table is a user-defined table with one row per date and columns for various date-related attributes.

Example Schema

CREATE TABLE dbo.Calendar (
    CalendarDate     DATE PRIMARY KEY,
    Year             INT,
    Month            INT,
    Day              INT,
    Weekday          INT, -- 1=Sunday, 7=Saturday
    DayOfWeekName    VARCHAR(10),
    IsWeekend        BIT,
    IsHoliday        BIT,
    YearMonth        CHAR(6), -- e.g. '202504'
    Quarter          INT,
    DayOfYear        INT,
    WeekOfYear       INT,
    FiscalYear       INT,
    FiscalPeriod     INT
    -- Add more fields as needed
);

✅ Benefits

FeatureBenefit
🧠 ReadabilityEasier to understand and maintain date-related logic
🕵️‍♂️ SimplicityAvoids complex DATEPART or CASE expressions
🚀 PerformancePrecomputed attributes save CPU and memory during query time
📅 FlexibilityAdd columns like fiscal period, holiday flag, ISO week, etc.
📊 BI IntegrationWorks seamlessly with Power BI, SSAS, Tableau, and other tools

🧠 Example Use Case

SELECT 
    c.YearMonth,
    COUNT(*) AS WorkdayCount
FROM dbo.Calendar c
WHERE c.CalendarDate BETWEEN '2024-07-01' AND '2025-06-30'
  AND c.IsWeekend = 0
  AND c.IsHoliday = 0
GROUP BY c.YearMonth
ORDER BY c.YearMonth;

🔧 How to Populate It

Here’s how to generate dates and populate the calendar:

DECLARE @StartDate DATE = '2020-01-01';
DECLARE @EndDate   DATE = '2030-12-31';

WITH DateList AS (
    SELECT @StartDate AS CalendarDate
    UNION ALL
    SELECT DATEADD(DAY, 1, CalendarDate)
    FROM DateList
    WHERE CalendarDate < @EndDate
)
INSERT INTO dbo.Calendar (
    CalendarDate, Year, Month, Day, Weekday, DayOfWeekName,
    IsWeekend, YearMonth, Quarter, DayOfYear, WeekOfYear
)
SELECT 
    CalendarDate,
    YEAR(CalendarDate),
    MONTH(CalendarDate),
    DAY(CalendarDate),
    DATEPART(WEEKDAY, CalendarDate),
    DATENAME(WEEKDAY, CalendarDate),
    CASE WHEN DATENAME(WEEKDAY, CalendarDate) IN ('Saturday', 'Sunday') THEN 1 ELSE 0 END,
    FORMAT(CalendarDate, 'yyyyMM'),
    DATEPART(QUARTER, CalendarDate),
    DATEPART(DAYOFYEAR, CalendarDate),
    DATEPART(WEEK, CalendarDate)
FROM DateList
OPTION (MAXRECURSION 0);

🧩 Add Holiday Info

Assuming you maintain a dbo.Holidays table:

UPDATE c
SET c.IsHoliday = 1
FROM dbo.Calendar c
JOIN dbo.Holidays h ON c.CalendarDate = h.HolidayDate;

🏁 Final Thoughts

Creating and using a permanent calendar table ensures:

  • Better performance
  • Reusable logic
  • Cleaner, more maintainable SQL

💡 Tip: Build it once, use it everywhere!

MS-SQL查詢時產出日曆天暫存Table的方法

🗓️ Two Approaches to Generating Calendar Dates in SQL Server

When working with time-based reporting or scheduling systems, it’s often necessary to generate a list of calendar dates. Whether you’re counting workdays, building timelines, or joining with other datasets, having a calendar table—or generating dates on the fly—is crucial. Let’s explore two popular methods of generating calendar dates in SQL Server.


✅ 1. Using a Recursive CTE (Common Table Expression)

A recursive CTE can dynamically generate a list of dates without relying on any external table:

WITH Calendar AS (
    SELECT CAST('2024-07-01' AS DATE) AS DateValue
    UNION ALL
    SELECT DATEADD(DAY, 1, DateValue)
    FROM Calendar
    WHERE DateValue < '2025-06-30'
)
SELECT * FROM Calendar
OPTION (MAXRECURSION 0);

🔍 Pros:

  • No dependency on system tables.
  • Simple and self-contained.

⚠️ Cons:

  • Slightly less performant for very large ranges.
  • MAXRECURSION default is 100; you must override it for larger date ranges.

✅ 2. Using master.dbo.spt_values (or a numbers/tally table)

This system table contains thousands of rows and can be repurposed to generate sequential numbers (and thus, dates):

SELECT DATEADD(DAY, number, '2024-07-01') AS DateValue
FROM master.dbo.spt_values
WHERE type = 'P'
  AND number BETWEEN 0 AND DATEDIFF(DAY, '2024-07-01', '2025-06-30');

🔍 Pros:

  • Faster performance for large sets.
  • No recursion required.

⚠️ Cons:

  • Relies on an undocumented system table (spt_values), which may be unsupported or unavailable in some SQL Server environments (especially Azure SQL DB).
  • Less self-explanatory for beginners.

🧠 When to Use Which?

Use CaseRecommended Method
Small date ranges (e.g. 1 year)Recursive CTE
Large date ranges (many years)Tally table or spt_values
Need portability and readabilityRecursive CTE
Need performanceTally/spt_values

🏁 Conclusion

Both approaches have their place. The recursive CTE is elegant and portable, great for small to medium needs. If you’re working with large datasets or care about performance, using spt_values (or better, your own numbers table) is a strong alternative.

-- Suggested: Create your own Numbers table for safety
CREATE TABLE dbo.Numbers (n INT PRIMARY KEY);
WITH E1(n) AS (
    SELECT 1 UNION ALL SELECT 1 UNION ALL SELECT 1 UNION ALL SELECT 1
),
E2(n) AS (
    SELECT 1 FROM E1 a CROSS JOIN E1 b  -- 16 rows
),
E4(n) AS (
    SELECT ROW_NUMBER() OVER (ORDER BY (SELECT NULL)) - 1 AS n FROM E2 a CROSS JOIN E2 b
)
INSERT INTO dbo.Numbers(n)
SELECT n FROM E4 WHERE n < 10000;

👉 Tip: For production systems, consider creating a permanent Calendar table with pre-generated dates and useful attributes (week number, holiday flag, etc.) to simplify your queries.

在 Excel 2010 中建立並使用自訂列表進行排序,可用於樞紐分析

1.點擊檔案=>點擊左側欄的選項=>在 Excel 選項 視窗中,從左側窗格選擇進階=>一般,然後點擊編輯自訂列表按鈕。
在 自訂列表 對話框中:在列表項目」框中,輸入您的自訂順序,每項一行
點擊 新增 以儲存列表。該列表將出現在左側的「自訂列表」框中。
點擊 確定 關閉 自訂列表 對話框,再點擊 確定 退出 Excel 選項。

2.將自訂列表排序應用於樞紐分析表:
點擊樞紐分析表內的任意位置以啟動它。
點擊樞紐分析表中欄位標籤旁的下拉箭頭。
選擇 排序 > 更多排序選項。在 排序 對話框中:
選擇 升序 (A 到 Z) 或 降序 (Z 到 A)(升序將遵循您的自訂列表順序;降序將反轉它)。
取消勾選「每次更新報表時自動排序」(若已勾選)。
在「第一個鍵排序順序」下,從下拉選單中選擇您的自訂列表。
點擊 確定,然後再次點擊確定以應用排序。

使用Office 2003開啟Office 2007格式的Word、Excel檔案,出現 “轉換程式無法儲存檔案” 訊息

可能是檔案格式相容性套件FileFormatConverters版本較舊,在網路搜尋找到軟體王下載連結。先移除舊版,安裝新版後,可正常開啟。

小版本差異如下圖

EPSON L3210故障燈號三燈閃爍故障排除

1.檢查燈號和印表機狀態 參考EPSON官網異常燈號說明。

2.三燈閃爍判斷非為一般紙張或墨水異常。

3.拆除左側板並掀開掃描模組,檢視異物與破碎紙張。(參考youtube HOW TO REMOVE SCANNER EPSON L3210)

4.以空壓機噴氣清潔內部後,裝回測試正常。

Dell i3 電腦作業系統Windows 10,透過HDMI轉VGA接頭連接舊螢幕,開機螢幕偏黃,重新插拔連接線後恢復正常,異常排除。

更換VGA連接線=>更換螢幕=>更換轉接頭=>更新BIOS與intel顯卡驅動=>安裝AVAST防毒軟體=>移除最近安裝應用軟體(Microsoft Power Automate)=>進入intel顯卡設定程式任意調整設定(非相關設定)=>恢復正常

問題推斷,使用者反應自從另一位同事幫忙安裝Microsoft Power Automate後,桌面背景不定時會自行替換,檢查發現該人員安裝MPA時有微軟帳號登入,並有開啟桌面同步功能,關閉桌面同步後,桌面背景就不會自行變換,推斷此同步設定可能會影響開機時螢幕顯示相關設定,進入顯卡設定任意調整後可覆蓋此問題,因此可解決此異常,後續持續觀察。

Windows 11 無法新增網芳印表機0x00000709,0x000006d1

win11 22H2更新導致無法連線分享印表機

Code:
Windows Registry Editor Version 5.00

[HKEY_LOCAL_MACHINE\SOFTWARE\Policies\Microsoft\Windows NT\Printers\RPC]
"RpcUseNamedPipeProtocol"=dword:00000001
"RpcProtocols"=dword:00000007
"ForceKerberosForRpc"=dword:00000001

[HKEY_LOCAL_MACHINE\System\CurrentControlSet\Control\Print]
"RpcAuthnLevelPrivacyEnabled"=dword:00000000

fix print spooler https://www.sordum.org/9199/fix-print-spooler-v1-3/

在win10連線到win11分享之印表機,以上方法都沒用,移除所有可移除更新也都沒用,執行fix print spooler,然後新增local port印表機方式連線成功。

ms-sql–lead抓取與下筆資料日期差異天數,依群組條件(每月)重置,該月最後一筆天期計算至下月初

SELECT 
    t1.TransactionType,
    t1.TransactionDate,
    YEAR(t1.TransactionDate) AS TransactionYear,
    MONTH(t1.TransactionDate) AS TransactionMonth,
    LEAD(t1.TransactionDate, 1, DATEADD(day, 1, EOMONTH(t1.TransactionDate)))
            OVER (PARTITION BY t1.TransactionType,YEAR(t1.TransactionDate),MONTH(t1.TransactionDate) ORDER BY t1.TransactionDate) AS NextTransactionDate,
    DATEDIFF(day, t1.TransactionDate, 
        LEAD(t1.TransactionDate, 1, DATEADD(day, 1, EOMONTH(t1.TransactionDate)))
            OVER (PARTITION BY t1.TransactionType,YEAR(t1.TransactionDate),MONTH(t1.TransactionDate) ORDER BY t1.TransactionDate)) AS DifferenceInDays
FROM Transactions t1
GROUP BY 
    t1.TransactionType,
    t1.TransactionDate,
    YEAR(t1.TransactionDate),
    MONTH(t1.TransactionDate)
ORDER BY 
    t1.TransactionType,
    t1.TransactionDate;

LEAD (scalar_expression [,offset] [,default])
OVER ( [ partition_by_clause ] order_by_clause )  provides access to a row at a specified physical offset which follows the current row. It allows you to query more than one row in a SQL statement without having to join the table to itself

The  EOMONTH function in SQL is used to get the last day of the month for a specified date

DATEADD(day, 1, EOMONTH(t1.TransactionDate)) 找出月底再+1得到下月初

Excel Delete Rows Based On Criteria以巨集刪除特定條件之資料,如某欄資料空白

Sub DeleteRowsBasedOnCriteria()
    Dim ws As Worksheet
    Dim lastRow As Long
    Dim i As Long
    Dim deleteFlag As Boolean
    Dim concatenateString As String

    ' Set the active sheet as the worksheet
    Set ws = ActiveSheet

    ' Find the last row in column A
    lastRow = ws.Cells(ws.Rows.Count, "A").End(xlUp).Row

    ' First pass: Mark rows for deletion based on the first criteria
    For i = lastRow To 1 Step -1
        ' Initialize deleteFlag to False for each row
        deleteFlag = False

        ' Check if any of the columns A through H is empty
        For j = 1 To 8 ' Columns A through H
            If ws.Cells(i, j).Value = "" Then
                ' Set the deleteFlag to True if any column is empty
                deleteFlag = True
                Exit For
            End If
        Next j

        

        ' Delete the entire row if any column A through H is empty or if the concatenation matches
        If deleteFlag Then
            ws.Rows(i).Delete
        End If
    Next i

    ' Find the last row again after the first deletion
    lastRow = ws.Cells(ws.Rows.Count, "A").End(xlUp).Row

    ' Second pass: Delete rows based on the second criteria
    For i = lastRow To 1 Step -1
        ' Check if the concatenation of the first 9 columns equals a specific string
        concatenateString = ""
        For j = 1 To 9 ' Columns A through I
            concatenateString = concatenateString & ws.Cells(i, j).Value
        Next j

        ' Delete the entire row if the concatenation matches the specific string
        If concatenateString = "訂單號碼訂單日預定出港日品名台灣品名數量/KGS包裝方式目的地備註" Then
            ws.Rows(i).Delete
        End If
    Next i
End Sub

Powershell script透過outlook每日發送刷卡資料

新增powershell script 檔案sendmail2.ps1 內容如:

$From = "0420@company.com.tw"
$To = "0420@company.com.tw","11010@company.com.tw","0260@company.com.tw","0410@company.com.tw"
$Subject = "card datas - $(Get-Date -Format 'yyyy-MM-dd')"
$Body = "card datas"
$AttachmentPath = "H:\RecData.txt"  # Specify the path to your attachment

Send-MailMessage -From $From -To $To -Subject $Subject -Body $Body -SmtpServer "192.168.x.x" -Attachments $AttachmentPath

新增工作排程 啟動程式 powershell.exe 新增引數-ExecutionPolicy Bypass -File ” C:\Users\user31\Desktop\sendmail2.ps1″