Si una "ausencia" se define como la no aparición de una fila en el emp_tx
tabla para un empcode
particular para una fecha en particular (fecha=medianoche a medianoche en un período de 24 horas) y...
Si es aceptable no mostrar una "ausencia" para una fecha cuando NO hay transacciones en el emp_tx
tabla para esa fecha (es decir, excluir una fecha cuando TODOS los códigos de inserción están ausentes en esa fecha), luego...
Puede obtener las primeras cuatro columnas del conjunto de resultados especificado con una consulta como esta:(no probado)
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
Obtener esa quinta columna TotalNoofAbsent
devuelto en el mismo conjunto de resultados es posible, pero hará que la consulta sea realmente complicada. Este detalle podría manejarse de manera más eficiente en el lado del cliente, al procesar el conjunto de resultados devuelto.
Cómo funciona la consulta
La vista en línea con alias como d
nos obtiene un conjunto de valores de "fecha" que estamos comprobando. Usando el emp_tx
table como fuente de estos valores de "fecha" es una forma conveniente de hacer esto. No el DATE()
la función devuelve solo la parte de "fecha" del argumento DATETIME; estamos usando un GROUP BY
para obtener una lista distinta de fechas (es decir, sin valores duplicados). (Lo que buscamos, con esta consulta de vista en línea, es un conjunto distinto de valores de FECHA entre los dos valores pasados como argumentos. Hay otras formas más complejas de generar una lista de valores de FECHA).
Siempre que cada valor de "fecha" que considerará como una "ausencia" aparezca en algún lugar de la tabla (es decir, al menos un empcode
tenido una transacción en cada fecha que sea de interés), y siempre que el número de filas en el emp_tx
table no es excesiva, entonces la consulta de vista en línea funcionará razonablemente bien.
(NOTA:la consulta en la vista en línea se puede ejecutar por separado, para verificar que los resultados sean correctos y como esperamos).
El siguiente paso es tomar los resultados de la vista en línea y realizar una CROSS JOIN
operación (para generar un producto cartesiano) para que coincida con CADA empcode
con CADA date
devuelto desde la vista en línea. El resultado de esta operación representa cada ocurrencia posible de "asistencia".
El paso final en la consulta es realizar una operación "anti-unión", usando un LEFT JOIN
y un WHERE IS NULL
predicado. El LEFT JOIN
(unión externa) devuelve todas las ocurrencias de asistencia posibles (desde el lado izquierdo), INCLUYENDO aquellas que no tienen una fila coincidente (registro de asistencia) del emp_tx
mesa.
El "truco" es incluir un predicado (en la cláusula WHERE) que descarte todas las filas donde se encontró un registro de asistencia coincidente, de modo que lo que nos quede sean todas las combinaciones de empcode
y date
(posibles ocurrencias de asistencia) donde NO hubo transacción de asistencia COINCIDENTE.
(NOTA:he dejado a propósito las referencias a la columna s_date (DATETIME) "desnudas" en los predicados y he usado predicados de rango. Esto permitirá que MySQL haga un uso efectivo de un índice apropiado que incluya esa columna).
Si tuviéramos que envolver las referencias de columna en los predicados dentro de una función, p. DATE(p.s_date)
, MySQL no podrá hacer un uso efectivo de un índice en el s_date
columna.
Como señala uno de los comentarios (sobre su pregunta), no estamos haciendo ninguna distinción entre las transacciones que marcan a un empleado como "entrante" o "saliente". SOLAMENTE buscamos la existencia de una transacción para ese código de inserción en un período determinado de 24 horas de "medianoche a medianoche".
Existen otros enfoques para obtener el mismo conjunto de resultados, pero el patrón "anti-unión" suele dar el mejor rendimiento con conjuntos grandes.
Para obtener el mejor rendimiento, es probable que desee cubrir índices:
... ON master (empcode, name, dept)
... ON emp_tx (s_date, empcode)