PHP MYSQLI计算用户连续两个日期

时间:2017-08-03 22:29:43

标签: php mysql mysqli

如何才能连续两次缺勤统计用户?我必须创建一个图表来显示员工的频繁缺勤情况。

我的表名= incidencias

id | name | dateA     | description
1  | al   |2017-08-01| absence
2  | al   |2017-08-02| absence
3  | alex |2017-08-01| absence
4  | alex |2017-08-02| absence
5  | alex |2017-08-03| absence
6  | al2  |2017-08-01| absence
7  | al2  |2017-08-02| absence

我希望结果为2,只有al和al2有两个连续的日期,其中description =缺席。

我使用php来运行查询,我确实尝试了这个代码我发现但是我在sqlfiddle中测试它并且效果很好。但不是在我的主机上。我认为这是针对PostgreSQL的。

$query2 = mysqli_query($conn, "SELECT name,
                sum(diff) as days, 
                (dateA) as work_start, 
                (dateA) as work_end 
            FROM (SELECT name,
                    dateA, 
                    diff 
            FROM (select name, 
                    dateA,
                    nvl(dateA- lag(dateA) over (partition by name order by dateA),1) as diff 
            from incidencias 
            where description = 'absence'
            ) t1 
            where diff = 1 
            ) t2 
            group by name
            having sum(diff) = 2");

$row_cnt = mysqli_num_rows($query2);

printf("Result set has %d rows.\n", $row_cnt);

我真的很感激。

2 个答案:

答案 0 :(得分:1)

所以,这通常是通过JOIN到同一张桌子来完成的。

SELECT oinc.* 
FROM incidencias oinc
LEFT JOIN 
     incidencias iinc
     ON (oinc.name = iinc.name AND oinc.description = iinc.description)
WHERE description = 'absence' 
     AND oinc.dateA = DATE_ADD( iinc.dateA, 'INTERVAL 1 DAY');

所以,逐行:

SELECT oinc.* -- grab me everything from the oinc table

FROM incidencias oinc -- We're going to call incidencias "oinc" in this query
                      -- "oinc" is now an alias for "incidencias"

LEFT JOIN -- I want a result whether or not the result is duplicated.
          -- (Technically, by including the condition that it not be duplicated
          -- this is the same thing as an "INNER JOIN".)

incidencias iinc -- We're looking at the same table, better call it something else

ON (oinc.name = iinc.name AND oinc.description = iinc.description) 
   -- We're matching the name and the description between the two
   -- aliases of the table (oinc, iicn)

WHERE description = 'absence' -- Should be obvious
    AND oinc.dateA = DATE_ADD( iinc.dateA, 'INTERVAL 1 DAY'); -- the iinc alias
           -- has a date which is one day less than the oinc alias

一些旁注:

  • 我使用left加入,以便您稍后可以省略AND ...
  • 您应该尝试将AND查询从WHERE移到ON子句中。然后,您可以使用INNER加入。你会得到相同的结果,但知道这两个结果会在以后帮助你。

答案 1 :(得分:0)

这是一种方式(可能有一个更简单的解决方案,但无论如何这应该很快)...

SELECT COUNT(*)
  FROM 
     ( SELECT name 
            , MAX(i) i
         FROM 
            ( SELECT x.*
                   , CASE WHEN @prev_name = name THEN 
                       CASE WHEN @prev_date = datea - INTERVAL 1 DAY THEN @i:=@i+1 ELSE @i:=1 END 
                       ELSE @i:=1 END i
                   , @prev_name := name
                   , @prev_date := datea
                FROM my_table x
                   , ( SELECT @prev_name:=null,@prev_date:=null, @i:=1) vars 
               WHERE x.description = 'absence'
               ORDER 
                  BY name
                   , datea
            ) b
        GROUP
           BY name
       HAVING i = 2
     ) p;