簡體   English   中英

MySQL基於兩個日期之間的聯接兩個表

[英]Mysql join two table based on between dates

我在mysql數據庫中有一個學生出勤視圖,如下所示

id    date         grade
239   01/09/2012   1
239   02/09/2012   0
239   04/09/2012   0
239   05/09/2012   1
239   07/09/2012   0
239   25/09/2012   0
239   26/09/2012   0

而且我在數據庫中還有一個請假申請表,如下所示。 其中批准= 1,拒絕= 0。

id  uid    from            to           status
 1   239    04/09/2012    07/09/2012  approved
 2   239    26/09/2012    26/09/2012  rejected

現在我想創建一個查詢來顯示批准的假期和學生的最終成績,如下所示

id    date       grade    leave   Fgrade
239   01/09/2012   1                 1
239   02/09/2012   0                 0
239   04/09/2012   0       1         1
239   05/09/2012   1       1         1    
239   07/09/2012   0       1         1
239   25/09/2012   0                 0
239   26/09/2012   0                 0

請告訴我如何獲得此結果。

改性

(基於后面評論中的說明進行的修改:)

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通過解釋優化查詢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分配值。 否則,我們為fgrade分配1。

根據對您問題的評論,可以將對作為IF函數中第三個參數的文字1的引用替換為Leave_application中的status列。 如果學生被授予休假,但同時也獲得了成績,則添加成績和休假狀態可能會獲得比您想要的更高的價值。 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'字符串,則可以調整查詢。 休假列的值可能不是id。 從示例數據中無法得知,因為請假的值與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

嘗試

SELECT a.id, a.date, a.grade,
       CASE WHEN l.status = 'approved' THEN 1 END `leave`,
       CASE WHEN l.status = 'approved' THEN 1 ELSE a.grade END fgrade
  FROM attendance a LEFT JOIN `leave` l
    ON a.id = l.uid 
   AND a.date BETWEEN l.from AND l.to

輸出:

|  ID |       DATE | GRADE |  LEAVE | FGRADE |
----------------------------------------------
| 239 | 2012-09-01 |     1 | (null) |      1 |
| 239 | 2012-09-02 |     0 | (null) |      0 |
| 239 | 2012-09-04 |     0 |      1 |      1 |
| 239 | 2012-09-05 |     1 |      1 |      1 |
| 239 | 2012-09-07 |     0 |      1 |      1 |
| 239 | 2012-09-25 |     0 | (null) |      0 |
| 239 | 2012-09-26 |     0 | (null) |      0 |

這是SQLFiddle演示

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM