【问题标题】:sql - get consecutive presents and absencessql - 获取连续的礼物和缺席
【发布时间】:2014-12-27 08:21:17
【问题描述】:

我正在为一个教堂开发一个出勤监控数据库应用程序,其目标是获取每个成员的连续出席和缺席情况。但连续计数将基于周

例如,我们每周有 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 次连续缺席,

我还必须知道连续词是在场还是不在场

请帮忙,提前谢谢

到目前为止,我通过循环查询完成了我的目标,但我认为循环多个查询是不可取的

【问题讨论】:

  • 请使用哪个 RDBMS(Sql Server、MySql、Oracle 等)
  • 你为什么关心谁出现?
  • @Strawberry,在我们的教会,如果有成员连续两周或以上缺席,他们将被列入需要探视的名单,一些接近他们的成员会探访他们以了解是否他们有问题

标签: mysql sql


【解决方案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,您可以使用与上述类似的技术来查找每个成员的差距。

希望对你有帮助。

【讨论】:

  • 不客气。如果您认为答案有用,您可以投票和/或接受它作为答案。 Korianders 解决方案也是如此。
【解决方案2】:

一种解决方案是使用会话变量,例如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;

连续的周被序列的第一周替换。从这里,您可以在此查询上“分组依据”,按 start_sequence,“计数”一周中出现的次数,并丢弃仅出现一次的那些。

它还没有返回缺席,但这可以通过

a) 正确加入包含您想要的所有周数的查找表

b) 使用负数表示缺勤的周数

【讨论】:

    猜你喜欢
    • 2021-03-15
    • 2017-06-02
    • 1970-01-01
    • 2017-10-17
    • 2023-03-08
    • 1970-01-01
    • 1970-01-01
    • 2013-05-18
    • 1970-01-01
    相关资源
    最近更新 更多