2017-08-03 12 views
1

如何计算连续两次缺席的用户?我必须创建一张图表来显示员工缺勤频率。PHP 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,只有人与AL2已经连续两个日期,其中描述=缺席。

我正在使用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); 

我真的很感激它。

+0

能否请您发布的SQL格式的一些示例数据? – sumit

回答

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 ...
  • 您应该尝试将WHERE中的AND查询移动到ON子句中。然后你可以使用INNER加入。你会得到同样的结果,但了解这两者后会对你有所帮助。
+0

不错。不完整。 – Strawberry

+0

(这是一个内部连接 ​​- 正如EXPLAIN EXTENDED,接下来是SHOW WARNINGS会演示的) – Strawberry

+0

@Strawberry想法通过提示“LEFT JOIN”我会给他更多的选项以便随后查询。 – cwallenpoole

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:[email protected]+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;