SQL Server 日期查詢範例

假設資料庫為出勤記錄表如下,並使用sql進行查詢:

CREATE TABLE [dbo].[AttendanceCollect](
	[CardCode] [nvarchar](200) NULL,
	[EmployeeName] [nvarchar](200) NULL,
	[EmployeeCode] [nvarchar](200) NULL,
	[AttendanceDate] [datetime] NULL, 
	[AttendanceTime] [nvarchar](200) NULL
)

一般日期查詢

在使用sql進行一般日期查詢時,您可以參考以下範例。

✅ 查詢特定日期(例如 2025-06-23)的打卡紀錄:

SELECT *
FROM [dbo].[AttendanceCollect]
WHERE CAST([AttendanceDate] AS DATE) = '2025-06-23';

✅ 查詢特定日期範圍(例如 2025-06-01 到 2025-06-23)的紀錄:

SELECT *
FROM [dbo].[AttendanceCollect]
WHERE [AttendanceDate] >= '2025-06-01'
  AND [AttendanceDate] < '2025-06-24';

注意這種「小於隔天」的寫法可以避免 datetime 時間部分的干擾。

✅ 查詢今天的打卡紀錄:

SELECT *
FROM [dbo].[AttendanceCollect]
WHERE CAST([AttendanceDate] AS DATE) = CAST(GETDATE() AS DATE);

✅ 查詢某員工(如 EmployeeCode = ‘E001’)在某日的打卡記錄:

SELECT *
FROM [dbo].[AttendanceCollect]
WHERE CAST([AttendanceDate] AS DATE) = '2025-06-23'
  AND [EmployeeCode] = 'E001';

日期與時間組合 做排序或進一步處理,也可將 AttendanceDate + AttendanceTime 合併:

SELECT *,
       CONVERT(datetime, 
         FORMAT([AttendanceDate], 'yyyy-MM-dd') + ' ' + [AttendanceTime], 120
       ) AS FullDateTime
FROM [dbo].[AttendanceCollect]

如果 AttendanceTime 是如 '08:30:00' 格式,這樣可以合併成真正的完整時間戳。

✅ 查詢當月的打卡紀錄

SELECT *
FROM [dbo].[AttendanceCollect]
WHERE AttendanceDate >= DATEFROMPARTS(YEAR(GETDATE()), MONTH(GETDATE()), 1)
  AND AttendanceDate <  DATEADD(MONTH, 1, DATEFROMPARTS(YEAR(GETDATE()), MONTH(GETDATE()), 1));

說明:

  • DATEFROMPARTS(YEAR(GETDATE()), MONTH(GETDATE()), 1):取得當月第一天(例如:2025-08-01)
  • DATEADD(MONTH, 1, ...):取得下個月第一天(例如:2025-09-01)
  • < 下個月第一天 的寫法可以避免 datetime 精度影響

✅ 補充:只查當月最早與最晚打卡(報表格式)

SELECT 
    EmployeeCode,
    EmployeeName,
    CAST(AttendanceDate AS DATE) AS AttendanceDay,
    MIN(AttendanceTime) AS FirstCheckIn,
    MAX(AttendanceTime) AS LastCheckOut
FROM dbo.AttendanceCollect
WHERE AttendanceDate >= DATEFROMPARTS(YEAR(GETDATE()), MONTH(GETDATE()), 1)
  AND AttendanceDate <  DATEADD(MONTH, 1, DATEFROMPARTS(YEAR(GETDATE()), MONTH(GETDATE()), 1))
GROUP BY EmployeeCode, EmployeeName, CAST(AttendanceDate AS DATE)
ORDER BY EmployeeCode, AttendanceDay;

✅ 查詢上一個月的打卡紀錄

要查詢「上一個月的打卡紀錄」,可用 SQL Server 內建函數 GETDATE()DATEADD() 搭配 DATEFROMPARTS(),來取得上個月的第一天與最後一天(或隔月1日)

SELECT *
FROM [dbo].[AttendanceCollect]
WHERE AttendanceDate >= DATEFROMPARTS(YEAR(DATEADD(MONTH, -1, GETDATE())), MONTH(DATEADD(MONTH, -1, GETDATE())), 1)
  AND AttendanceDate <  DATEFROMPARTS(YEAR(GETDATE()), MONTH(GETDATE()), 1);

🔍 範例(假設今天是 2025-08-07):

  • DATEADD(MONTH, -1, GETDATE()) → 2025-07-07
  • DATEFROMPARTS(YEAR(...), MONTH(...), 1) → 2025-07-01
  • DATEFROMPARTS(YEAR(GETDATE()), MONTH(GETDATE()), 1) → 2025-08-01

所以查詢區間會是:
👉 2025-07-01 <= AttendanceDate < 2025-08-01

✅ 補充:上一個月的「最早/最晚打卡報表」

SELECT 
    EmployeeCode,
    EmployeeName,
    CAST(AttendanceDate AS DATE) AS AttendanceDay,
    MIN(AttendanceTime) AS FirstCheckIn,
    MAX(AttendanceTime) AS LastCheckOut
FROM dbo.AttendanceCollect
WHERE AttendanceDate >= DATEFROMPARTS(YEAR(DATEADD(MONTH, -1, GETDATE())), MONTH(DATEADD(MONTH, -1, GETDATE())), 1)
  AND AttendanceDate <  DATEFROMPARTS(YEAR(GETDATE()), MONTH(GETDATE()), 1)
GROUP BY EmployeeCode, EmployeeName, CAST(AttendanceDate AS DATE)
ORDER BY EmployeeCode, AttendanceDay;

出勤報表查詢

報表一:某日每位員工的最早與最晚打卡時間

SELECT 
    EmployeeCode,
    EmployeeName,
    CAST(AttendanceDate AS DATE) AS AttendanceDay,
    MIN(AttendanceTime) AS FirstCheckIn,
    MAX(AttendanceTime) AS LastCheckOut
FROM dbo.AttendanceCollect
WHERE CAST(AttendanceDate AS DATE) = '2025-06-23'
GROUP BY EmployeeCode, EmployeeName, CAST(AttendanceDate AS DATE)
ORDER BY EmployeeCode;

報表二:某一段時間內,員工們的每日打卡最早/最晚時間

SELECT 
    EmployeeCode,
    EmployeeName,
    CAST(AttendanceDate AS DATE) AS AttendanceDay,
    MIN(AttendanceTime) AS FirstCheckIn,
    MAX(AttendanceTime) AS LastCheckOut
FROM dbo.AttendanceCollect
WHERE AttendanceDate >= '2025-06-01'
  AND AttendanceDate < '2025-07-01'
GROUP BY EmployeeCode, EmployeeName, CAST(AttendanceDate AS DATE)
ORDER BY EmployeeCode, AttendanceDay;

報表三:統計一段時間內各員工出勤天數

SELECT 
    EmployeeCode,
    EmployeeName,
    COUNT(DISTINCT CAST(AttendanceDate AS DATE)) AS AttendanceDays
FROM dbo.AttendanceCollect
WHERE AttendanceDate >= '2025-06-01'
  AND AttendanceDate < '2025-07-01'
GROUP BY EmployeeCode, EmployeeName
ORDER BY AttendanceDays DESC;

報表四:某員工某日的完整打卡記錄(時間排序)

SELECT 
    AttendanceTime
FROM dbo.AttendanceCollect
WHERE EmployeeCode = 'E001'
  AND CAST(AttendanceDate AS DATE) = '2025-06-23'
ORDER BY AttendanceTime;

報表五 :員工出勤月曆打卡紀錄格式(早上 / 晚上欄位)

SELECT CardCode
	,EmployeeCode
	,EmployeeName
	,CONVERT(DATE, DATE) AS [Date]
	,MIN(TIME) AS FirstCheckIn
	,MAX(TIME) AS LastCheckOut
FROM AttendanceCollect
WHERE DATE >= '2025-06-01'
	AND DATE < '2025-07-01'
	AND EmployeeCode IS NOT NULL
	AND CardCode IS NOT NULL
GROUP BY CardCode
	,EmployeeCode
	,EmployeeName
	,CONVERT(DATE, DATE)
ORDER BY CardCode
	,EmployeeCode
	,[Date];

發佈留言

發佈留言必須填寫的電子郵件地址不會公開。 必填欄位標示為 *


內容索引