我正在为教堂开发一个考勤监控数据库应用程序,其目的是为每个成员提供连续的出席和缺席。但连续计数将以周为基础
例如,我们每周有3个服务(一个星期一,一个星期三,一个星期五),但这些服务是相同的,(唯一的区别是时间/日期)。所以会员可以参加任何会议(他们可以参加所有会议)例如,我必须根据周找到每个成员的连续出席和缺席 如果我参加2014年12月的月份是:
S M T W T F S
W1 - P - P - - -
W2 - P - - - - -
W3 - P - P - P -
W4 - - - - - P -
W5 - P - - - - -
我有5个连续出席 我每周只能计算一次出席率(任何其他出席都会被忽略)
这是表格
tbl_members
member_id last_name first_name ... and so on
1 SANTIAGO JOHN KERNELLE
tbl_service_attendances
att_index service_date member_id
1 2014-12-01 1
2 2014-12-03 1
3 2014-12-08 1
4 2014-12-15 1
5 2014-12-17 1
6 2014-12-19 1
7 2014-12-26 1
8 2014-12-29 1
att_index是自动增量
每次参加会员时,我都会使用此查询:
INSERT INTO tbl_service_attendances(service_date, member_id) VALUES('2014-12-29', 1)
如果他们在一周内参加了8项服务,那么tbl_service_attendances将为每一项提供8行(唯一的区别是他们的日期)。但它只算作5个连续出席。 (每周一次)
S M T W T F S
W1 - P - P - - -
W2 - P - - - - -
W3 - P - P - P -
W4 - - - - - - -
W5 - - - - - - -
在这种情况下,我有2个连续吸收,
我还必须知道连任是否存在
请提前帮助,请提供帮助
到目前为止,我通过循环查询完成了我的目标,但我认为循环多个查询是不可取的
答案 0 :(得分:1)
首先,这种问题在支持窗口函数的DBMS中更容易处理,但这里有一个可以与MySQL一起使用的想法。让我们首先创建一个视图,以简化问题:
create view wa as select distinct member_id, week(service_date) as wk
from service_attendances;
我在这里假设我们正在处理一年的数据。如果不是年份必须包含在视图和下面的查询中。
根据这一观点,我们可以创建每周出勤的时间间隔:
select member_id, min(start_wk), end_wk
from (
select wa1.member_id, wa1.wk as start_wk, min(wa2.wk) as end_wk
from wa as wa1
join wa as wa2
on wa1.member_id = wa2.member_id
and wa2.wk > wa1.wk
and not exists (
select 1
from wa wa3
where wa2.member_id = wa3.member_id
and wa3.wk = wa2.wk + 1
)
group by wa1.wk, wa1.member_id
) as x
group by member_id, end_wk;
根据您在上面提供的数据,结果是:
+-----------+---------------+--------+
| member_id | min(start_wk) | end_wk |
+-----------+---------------+--------+
| 1 | 48 | 52 |
+-----------+---------------+--------+
可以很容易地从中得出差距。为这个表达式创建另一个视图是最容易的,但MySQL认为这是作弊:
ERROR 1349 (HY000): View's SELECT contains a subquery in the FROM clause
假设start_wk为1且end_wk为年份为52,您可以使用与上述类似的技术查找每个成员的差距。
希望它有所帮助。
答案 1 :(得分:1)
解决方案是使用会话变量,如此fiddle:
select IF (weekn = @prev + @n,
IF (@n := @n + 1, @prev, 1),
IF (@n:=0 OR @prev := weekn, weekn, 2)) start_sequence
from (select distinct week(service_date) as weekn
from tbl_service_attendances
where member_id = 1
and year(service_date) = 2014
and month(service_date) = 12
order by weekn) as presences
JOIN (SELECT @n := 0, @prev := week('2014-12-01')-2) AS setup;
连续几周被序列的第一周数替换。从这里,你可以" group by"在这个查询上,通过start_sequence," count"本周发生的次数,并丢弃仅发生一次的那些。
它还没有返回缺席,但这可以通过
来完成a)使用您想要的所有周数的查找表进行正确连接
b)使用负周数表示缺席数周