2017-08-03 1 views
1

Wie kann ich Benutzer mit zwei aufeinander folgenden Abwesenheiten nur zählen? Ich muss ein Diagramm erstellen, um Häufigkeitsabwesenheiten nach Mitarbeitern anzuzeigen.PHP MYSQLI Benutzer mit zwei aufeinander folgenden Daten zählen

Mein Tabellenname = 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 

Ich möchte das Ergebnis 2 sein, nur al und AL2 haben zwei aufeinanderfolgende Tage, wo description = Abwesenheit.

Ich benutze PHP, um die Abfrage auszuführen, habe ich diesen Code ich habe versucht, aber und ich testete es in sqlfiddle und funktioniert gut ,. aber nicht in meinem Host.Ich denke, das ist für 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); 

Ich würde es wirklich schätzen.

+0

Können Sie bitte einige Beispieldaten auf SQL-Format veröffentlichen? – sumit

Antwort

1

Dies geschieht normalerweise über JOIN in der gleichen Tabelle.

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'); 

Also, Zeile für Zeile:

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 

Einige Nebennoten:

  • I verwendet left verbinden, so dass Sie die AND ... später weglassen.
  • Sie sollten mit der AND Abfrage aus dem WHERE in den ON Abschnitt experimentieren. Dann können Sie einen INNER Join verwenden. Sie erhalten die gleichen Ergebnisse, aber beide zu kennen wird Ihnen später helfen.
+0

Schön. Unvollständig jedoch. – Strawberry

+0

(Und das ist ein innerer Join - wie EXPLAIN EXTENDED gefolgt von SHOW WARNINGS würde zeigen) – Strawberry

+0

@Strawberry Thought durch das Vorschlagen von "LEFT JOIN", dass ich ihm mehr Möglichkeiten geben würde, später mit der Abfrage zu spielen. – cwallenpoole

0

Hier ist eine Art und Weise (es kann eine einfachere Lösung sein, aber dies sollte schnell sein sowieso) ...

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; 
Verwandte Themen