「不在」がemp_tx
に行が表示されないこととして定義されている場合 特定のempcode
のテーブル 特定の日付(date =深夜から深夜24時間)、および...
emp_tx
にトランザクションがない日付に「不在」を表示しないことが許容される場合 その日付のテーブル(つまり、その日付にすべてのempcodeが存在しない日付を除外する)、次に...
次のようなクエリを使用して、指定した結果セットの最初の4列を取得できます:(未テスト)
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
その5番目の列を取得するTotalNoofAbsent
同じ結果セットで返される可能性はありますが、そのクエリは非常に面倒になります。この詳細は、返された結果セットを処理するときに、クライアント側でより効率的に処理される可能性があります。
クエリの仕組み
d
としてエイリアスされたインラインビュー チェックしている「日付」値のセットを取得します。 emp_tx
を使用する これらの「日付」値のソースとしてのテーブルは、これを行うための便利な方法です。 DATE()
ではありません 関数は、DATETIME引数の「日付」部分のみを返します。 GROUP BY
を使用しています 日付の明確なリストを取得します(つまり、重複する値はありません)。 (このインラインビュークエリで求めているのは、引数として渡された2つの値の間にある別個のDATE値のセットです。DATE値のリストを生成する他のより複雑な方法があります。)
「不在」と見なすすべての「日付」値がテーブルのどこかに表示されている限り(つまり、少なくとも1つのempcode
関心のある各日付に1つのトランザクションがあり、emp_tx
の行数である限り テーブルが多すぎない場合は、インラインビュークエリが適切に機能します。
(注:インラインビューのクエリを個別に実行して、結果が正しく、期待どおりであることを確認できます。)
次のステップは、インラインビューから結果を取得し、CROSS JOIN
を実行することです。 すべてのempcode
に一致する操作(デカルト積を生成するため) すべてのdate
インラインビューから返されます。この操作の結果は、「出席」のすべての可能な発生を表します。
クエリの最後のステップは、LEFT JOIN
を使用して、「アンチジョイン」操作を実行することです。 およびWHERE IS NULL
述語。 LEFT JOIN
(外部結合)は、emp_tx
からの一致する行(出席レコード)がないものを含め、(左側から)可能なすべての出席の発生を返します。 テーブル。
「トリック」は、一致する出席レコードが見つかったすべての行を破棄する述語を(WHERE句に)含めることです。そのため、残っているのはempcode
のすべての組み合わせです。 およびdate
(出席の可能性があります)一致する出席トランザクションがなかった場合。
(注:述語にs_date(DATETIME)列 "bare"への参照を意図的に残し、範囲述語を使用しました。これにより、MySQLはその列を含む適切なインデックスを効果的に使用できるようになります。)
>
関数内の述語で列参照をラップする場合、たとえば、 DATE(p.s_date)
、その場合、MySQLはs_date
のインデックスを効果的に使用できなくなります 列。
(あなたの質問に対する)コメントの1つが指摘しているように、従業員を「入ってきた」または「出て行った」とマークするトランザクションを区別していません。与えられた24時間の「真夜中から真夜中」の期間にそのempcodeのトランザクションの存在のみを探しています。
同じ結果セットを取得する方法は他にもありますが、「反結合」パターンは通常、大きなセットで最高のパフォーマンスを発揮することがわかります。
最高のパフォーマンスを得るには、インデックスをカバーすることをお勧めします:
... ON master (empcode, name, dept)
... ON emp_tx (s_date, empcode)