修正済み
(後のコメントで提供された説明に基づく変更:)
SELECT a.id
, a.date
, a.grade
, NULLIF(MAX(l.id) IS NOT NULL,0) AS leave
, IF(MAX(l.id) IS NULL,a.grade,1) AS fgrade
FROM student_attendance a
LEFT
JOIN leave_application l
ON l.uid = a.id
AND l.from <= a.date
AND l.to + INTERVAL 1 DAY > a.date
AND l.status = 'Approved'
GROUP BY a.id, a.date, a.grade
パフォーマンスのために、おそらくインデックスが必要です
... ON `student_attendance` (`id`, `date`, `grade`)
... ON `leave_application` (`uid`, `status`, `from`, `to`, `uid`)
EXPLAIN SELECT ... を使用して、アクセス プランに関する情報を取得できます。
8.8.1 Explain を使用したクエリの最適化 http://dev.mysql.com/doc/refman/5.5/en/using-explain.html
ついさっき:
これは指定された結果セットを返すと思います。
SELECT a.id
, a.date
, a.grade
, l.id AS leave
, IF(l.id IS NULL,a.grade,1) AS fgrade
FROM student_attendance a
LEFT
JOIN leave_application l
ON l.uid = a.id
AND l.from <= a.date
AND l.to >= a.date
AND l.status = 1 /* approved */
JOIN 述語は、学生 ID と一致し、休暇期間内の出席日の範囲チェックと、休暇が承認されています。
一致する (重複する) 休暇行がない場合、fgrade には grade 列の値が割り当てられます。それ以外の場合は、fgrade に 1 を割り当てます。
あなたの質問に残されたコメントに基づいて、IF 関数の 3 番目の引数としてのリテラル 1 は、leave_application からのステータス列への参照に置き換えることができます。成績と休暇ステータスを追加すると、学生が休暇を許可されたが成績も取得した場合、希望よりも高い値になる可能性があります。1+1=2。
IF(l.id IS NULL,a.grade,l.status) AS fgrade
Student_attendance の行が leave_application テーブルの複数の行と一致する可能性があります。GROUP BY と集計でこれに対処できます...
SELECT a.id
, a.date
, a.grade
, MAX(l.id) AS leave
, IF(MAX(l.id) IS NULL,a.grade,1) AS fgrade
FROM student_attendance a
LEFT
JOIN leave_application l
ON l.uid = a.id
AND l.from <= a.date
AND l.to >= a.date
AND l.status = 1 /* approved */
GROUP BY a.id, a.date, a.grade
status
が実際に を含む文字列の場合'Approved'
、クエリを調整できます。leave 列のその値は ID ではない可能性があります。leave の値は ID とステータス「承認済み」の値 1 の両方と一致するため、サンプル データからはわかりません。したがって、その値は実際には
l.status AS leave
NULLIF(l.id IS NOT NULL,0) AS leave
IF(l.id IS NOT NULL,1,NULL) AS leave
(l.id/l.id) AS leave
これらの式のいずれでも、サンプル データに示されている結果が得られます。
繰り返しますが、質問へのコメントで提供された追加情報に基づいて...
SELECT a.id
, a.date
, a.grade
, NULLIF(MAX(l.id) IS NOT NULL,0) AS leave
, IF(MAX(l.id) IS NULL,a.grade,1) AS fgrade
FROM student_attendance a
LEFT
JOIN leave_application l
ON l.uid = a.id
AND l.from <= a.date
AND l.to >= a.date
AND l.status = 'Approved'
GROUP BY a.id, a.date, a.grade