帮我写一段sql语句计算实际出勤天数
时间: 2023-05-23 08:02:54 浏览: 399
当然,我可以为您编写一段计算实际出勤天数的 SQL 语句。但是,我需要知道更多具体信息,例如,您要计算的日期范围、出勤记录表的结构等等。在了解更多背景信息后,我可以帮助您编写适合您实际需求的 SQL 语句。
相关问题
有一个员工日考勤统计数据,包含三列,员工ID、出勤日期、出勤时间,其中出勤时间大于0表示有出勤,出勤时间等于0表示未出勤,请帮我写一段sql查询语句,查询员工截止每个出勤日期的连续出勤天数
为了计算每位员工截至每个出勤日期为止的连续出勤天数,可以利用窗口函数和一些巧妙的时间差逻辑。以下是具体的SQL查询思路及实现步骤:
### SQL 查询
假设您的表名叫做 `attendance_table` ,结构为:
- `employee_id`: 员工ID
- `attendance_date`: 出勤日期
- `attendance_time`: 出勤时间(>0 表示已出勤,=0 或 NULL 表示未出勤)
#### 实现方案
我们先通过窗口函数对数据进行编号,再判断哪些日子是真正意义上的"断档"(即某天没打卡),以此为基础来计算连续工作日的数量。
```sql
WITH ContinuousAttendance AS (
SELECT
employee_id,
attendance_date,
attendance_time,
CASE WHEN LAG(attendance_time, 1) OVER w <= 0 OR attendance_time > 0 THEN ROW_NUMBER() OVER w ELSE 0 END -
ROW_NUMBER() OVER (PARTITION BY employee_id ORDER BY attendance_date) + 1 AS grp
FROM attendance_table
WINDOW w AS (PARTITION BY employee_id ORDER BY attendance_date)
),
GroupedContinuousDays AS (
SELECT *,
SUM(grp) OVER (PARTITION BY employee_id ORDER BY attendance_date) AS group_num
FROM ContinuousAttendance
)
SELECT
gcd.employee_id,
gcd.attendance_date,
COUNT(*) OVER (PARTITION BY gcd.employee_id, gcd.group_num ORDER BY gcd.attendance_date) AS consecutive_days
FROM GroupedContinuousDays gcd
WHERE gcd.attendance_time > 0; -- 只统计有效的工作日
ORDER BY gcd.employee_id, gcd.attendance_date;
```
**说明**
1. **第一步**: 使用窗口函数 `LAG()` 来查看前一天是否有记录,并结合 `ROW_NUMBER()` 计算当天是否应该属于新的连贯序列。
2. **第二步**: 对每一个新开始的连贯段赋予一个新的标识符 (`group_num`)。
3. **第三步**: 根据这个标识符再次分组并计数每一段内有多少个工作日。
最终输出包括三个字段:
- `employee_id`: 每位雇员的身份识别码;
- `attendance_date`: 当前检查的日志日期;
- `consecutive_days`: 截止到这一天该员工已经持续工作的总天数(仅当 `attendance_time` 大于零时才计入)。
这种方法能有效地追踪每个人每天的实际状态变化情况,并且准确地反映出他们各自最新的连续上班周期长度。
---
Oracle 获取当月出勤天数
要获取当月的出勤天数,可以使用如下的SQL查询语句:
```
SELECT COUNT(c.calendar_date) AS 出勤天数
FROM calendar c
CROSS JOIN employee e
LEFT JOIN attendance a ON a.check_date = c.calendar_date AND a.emp_id = e.emp_id
WHERE c.calendar_year = 2021
AND c.calendar_month = 1
AND c.is_work_day = 'Y'
AND (a.id IS NULL OR a.clock_in IS NULL OR a.clock_out IS NULL OR EXTRACT(HOUR FROM a.clock_in) >= 9 OR EXTRACT(HOUR FROM a.clock_out) < 18);
```
这个查询语句中,首先使用交叉连接(CROSS JOIN)将日历表和员工表进行连接,得到一个笛卡尔积,即所有员工每日的打卡记录。然后使用左连接(LEFT JOIN)将出勤表与这个笛卡尔积连接,以保留所有的日历日期。接着通过条件筛选出符合要求的记录,即缺勤、迟到或早退的情况。最后使用COUNT函数统计出勤天数,即出现在结果集中的日历日期的数量。<span class="em">1</span><span class="em">2</span>
#### 引用[.reference_title]
- *1* *2* [SQL案例学习-员工考勤记录](https://blog.csdn.net/liangmengbk/article/details/124154670)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 100%"]
[ .reference_list ]
阅读全文
相关推荐














