Wenn eine "Abwesenheit" als das Nichterscheinen einer Zeile im emp_tx
definiert ist Tabelle für einen bestimmten empcode
für ein bestimmtes Datum (Datum =Mitternacht bis Mitternacht 24-Stunden-Zeitraum) und ...
Wenn es akzeptabel ist, keine "Abwesenheit" für ein Datum anzuzeigen, an dem KEINE Transaktionen im emp_tx
vorhanden sind Tabelle für dieses Datum (d. h. ein Datum ausschließen, an dem ALLE Empcodes an diesem Datum fehlen), dann ...
Sie können die ersten vier Spalten der angegebenen Ergebnismenge mit einer Abfrage wie dieser abrufen:(ungetestet)
SELECT m.empcode AS `EmpCode`
, m.name AS `EmpName`
, m.dept AS `Department`
, d.dt AS `AbsentDate`
FROM ( SELECT DATE(t.s_date) AS dt
FROM emp_tx t
WHERE t.s_date >= '2012-12-12'
AND t.s_date < DATE_ADD( '2012-12-20' ,INTERVAL 1 DAY)
GROUP BY DATE(t.s_date)
ORDER BY DATE(t.s_date)
) d
CROSS
JOIN master m
LEFT
JOIN emp_tx p
ON p.s_date >= d.dt
AND p.s_date < d.dt + INTERVAL 1 DAY
AND p.empcode = m.empcode
WHERE p.empcode IS NULL
ORDER
BY m.empcode
, d.dt
Abrufen der fünften Spalte TotalNoofAbsent
in der gleichen Ergebnismenge zurückgegeben wird, ist möglich, aber es wird diese Abfrage wirklich chaotisch machen. Dieses Detail kann auf der Client-Seite effizienter gehandhabt werden, wenn die zurückgegebene Ergebnismenge verarbeitet wird.
Wie die Abfrage funktioniert
Die Inline-Ansicht mit dem Alias d
erhält uns eine Reihe von "date"-Werten, die wir überprüfen. Mit emp_tx
Tabelle als Quelle dieser "Datums"-Werte ist eine bequeme Möglichkeit, dies zu tun. Nicht das DATE()
Funktion gibt nur den "date"-Teil des DATETIME-Arguments zurück; wir verwenden ein GROUP BY
um eine eindeutige Datumsliste zu erhalten (d. h. keine doppelten Werte). (Was wir bei dieser Inline-Ansichtsabfrage anstreben, ist ein bestimmter Satz von DATE-Werten zwischen den beiden als Argumenten übergebenen Werten. Es gibt andere, kompliziertere Möglichkeiten, eine Liste von DATE-Werten zu generieren.)
Solange jeder "date"-Wert, den Sie als "Abwesenheit" betrachten, irgendwo in der Tabelle erscheint (d. h. mindestens ein empcode
an jedem interessierenden Datum eine Transaktion hatte) und solange die Anzahl der Zeilen in emp_tx
Tabelle nicht übermäßig ist, dann wird die Inline-Ansichtsabfrage einigermaßen gut funktionieren.
(HINWEIS:Die Abfrage in der Inline-Ansicht kann separat ausgeführt werden, um zu überprüfen, ob die Ergebnisse korrekt und wie erwartet sind.)
Der nächste Schritt besteht darin, die Ergebnisse aus der Inline-Ansicht zu nehmen und einen CROSS JOIN
durchzuführen Operation (um ein kartesisches Produkt zu erzeugen), um JEDEM empcode
zu entsprechen mit JEDEM date
aus der Inline-Ansicht zurückgegeben. Das Ergebnis dieser Operation repräsentiert jedes mögliche Auftreten von "Anwesenheit".
Der letzte Schritt in der Abfrage besteht darin, eine "Anti-Join"-Operation durchzuführen, indem ein LEFT JOIN
verwendet wird und ein WHERE IS NULL
Prädikat. Der LEFT JOIN
(Outer Join) gibt jedes mögliche Anwesenheitsvorkommen (von der linken Seite) zurück, EINSCHLIESSLICH derjenigen, die keine übereinstimmende Zeile (Anwesenheitsdatensatz) aus emp_tx
haben Tabelle.
Der „Trick“ besteht darin, ein Prädikat (in die WHERE-Klausel) aufzunehmen, das alle Zeilen verwirft, in denen ein übereinstimmender Anwesenheitsdatensatz gefunden wurde, sodass wir alle Kombinationen von empcode
übrig haben und date
(mögliche Anwesenheitsereignisse), bei denen es KEINE ÜBEREINSTIMMENDE Anwesenheitstransaktion gab.
(HINWEIS:Ich habe die Verweise auf die Spalte s_date (DATETIME) in den Prädikaten absichtlich "leer" gelassen und Bereichsprädikate verwendet. Dadurch kann MySQL einen geeigneten Index effektiv nutzen, der diese Spalte enthält.)
Wenn wir die Spaltenreferenzen in die Prädikate innerhalb einer Funktion einschließen würden, z. DATE(p.s_date)
, dann kann MySQL einen Index für s_date
nicht effektiv nutzen Spalte.
Wie einer der Kommentare (zu Ihrer Frage) betont, machen wir keinen Unterschied zwischen Transaktionen, die einen Mitarbeiter entweder als "kommend" oder "gehend" kennzeichnen. Wir suchen NUR nach der Existenz einer Transaktion für diesen Empcode in einem bestimmten 24-Stunden-Zeitraum von "Mitternacht bis Mitternacht".
Es gibt andere Ansätze, um die gleiche Ergebnismenge zu erhalten, aber das "Anti-Join"-Muster liefert normalerweise bei großen Mengen die beste Leistung.
Um die beste Leistung zu erzielen, möchten Sie wahrscheinlich abdeckende Indizes:
... ON master (empcode, name, dept)
... ON emp_tx (s_date, empcode)