You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

VB.NET实现员工月度考勤报表展示及SQL查询问题求助

Hey there! Let's break down your problem and fix it step by step.

First, why is your current query only returning 1 result? That's likely because only one employee has check-in records in April 2018 in your ATTENDANCE table. If you just want to see all employees for April (including those with zero check-ins), we'll cover that too—but let's start with your core goal: building an automatic monthly attendance report for all employees across all months.

Solution 1: Report attendance days per employee per month (only months with check-ins)

This query groups data by employee and month, so you'll get a row for every employee-month combination where there's at least one check-in. The syntax varies slightly by database:

MySQL/MariaDB

SELECT 
    EMPLOYEEID,
    DATE_FORMAT(checkinDate, '%Y-%m') AS report_month,
    COUNT(DISTINCT checkinDate) AS attendance_days
FROM ATTENDANCE
GROUP BY EMPLOYEEID, DATE_FORMAT(checkinDate, '%Y-%m')
ORDER BY EMPLOYEEID, report_month;

PostgreSQL

SELECT 
    EMPLOYEEID,
    DATE_TRUNC('month', checkinDate)::DATE AS month_start,
    COUNT(DISTINCT checkinDate) AS attendance_days
FROM ATTENDANCE
GROUP BY EMPLOYEEID, DATE_TRUNC('month', checkinDate)
ORDER BY EMPLOYEEID, month_start;

SQL Server

SELECT 
    EMPLOYEEID,
    DATEFROMPARTS(YEAR(checkinDate), MONTH(checkinDate), 1) AS month_start,
    COUNT(DISTINCT checkinDate) AS attendance_days
FROM ATTENDANCE
GROUP BY EMPLOYEEID, YEAR(checkinDate), MONTH(checkinDate)
ORDER BY EMPLOYEEID, month_start;

Solution 2: Full monthly report (include employees with zero check-ins)

If you need a complete report that shows every employee for every month (even if they never checked in that month), you'll need to generate a list of all months and all employees first, then join with the attendance data. Here's how to do it in MySQL:

-- Generate all months we want to report on (adjust start date as needed)
WITH all_months AS (
    SELECT DATE_FORMAT('2018-01-01' + INTERVAL (a.a + 10*b.a + 100*c.a) MONTH, '%Y-%m') AS report_month
    FROM (SELECT 0 AS a UNION ALL SELECT 1 UNION ALL SELECT 2 UNION ALL SELECT 3 UNION ALL SELECT 4 UNION ALL SELECT 5 UNION ALL SELECT 6 UNION ALL SELECT 7 UNION ALL SELECT 8 UNION ALL SELECT 9) a
    CROSS JOIN (SELECT 0 AS a UNION ALL SELECT 1 UNION ALL SELECT 2 UNION ALL SELECT 3 UNION ALL SELECT 4 UNION ALL SELECT 5 UNION ALL SELECT 6 UNION ALL SELECT 7 UNION ALL SELECT 8 UNION ALL SELECT 9) b
    CROSS JOIN (SELECT 0 AS a UNION ALL SELECT 1 UNION ALL SELECT 2) c
    WHERE '2018-01-01' + INTERVAL (a.a + 10*b.a + 100*c.a) MONTH <= CURDATE()
),
-- Get all unique employees (replace EMPLOYEE with your actual employee table name)
all_employees AS (
    SELECT DISTINCT EMPLOYEEID FROM EMPLOYEE
)
-- Combine everything and calculate attendance days
SELECT 
    ae.EMPLOYEEID,
    am.report_month,
    COALESCE(COUNT(DISTINCT a.checkinDate), 0) AS attendance_days
FROM all_employees ae
CROSS JOIN all_months am
LEFT JOIN ATTENDANCE a 
    ON ae.EMPLOYEEID = a.EMPLOYEEID 
    AND DATE_FORMAT(a.checkinDate, '%Y-%m') = am.report_month
GROUP BY ae.EMPLOYEEID, am.report_month
ORDER BY ae.EMPLOYEEID, am.report_month;

Fixing your original April-only query (show all employees)

If you just want to fix your original query to show all employees for April 2018 (including those with no check-ins), use a left join with your employee table:

SELECT 
    e.EMPLOYEEID,
    COUNT(DISTINCT a.checkinDate) AS April_attendance_days
FROM EMPLOYEE e
LEFT JOIN ATTENDANCE a 
    ON e.EMPLOYEEID = a.EMPLOYEEID 
    AND a.checkinDate BETWEEN '2018-04-01' AND '2018-04-30'
GROUP BY e.EMPLOYEEID
ORDER BY e.EMPLOYEEID;

This will return a row for every employee, with 0 if they had no check-ins in April.

内容的提问来源于stack exchange,提问作者Aaron Lee Herng Yue

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.25 03:50:59