2012-04-28 51 views
0

也許有人可以闡明,我一直在爭奪與整個一天:)使用3臺與狀態檢查一個棘手的SQL語句

聲明一些光我有3個表

假日

holidayID | userID | dateFrom | dateTo 
1   |  1 | 2012-01-01 | 2012-01-01 
2   |  1 | 2012-01-15 | 2012-01-20 

狀態

statusID | holidayID | statusText 
1  |   1 | accepted 
2  |   2 | declined 

UserSettings

id | userID | HolidaysAllowed 
1 |  1 | 20 

我所試圖做的是得到以下結果

結果

HolidaysAllowed | HolidaysLeft (Allowed - Taken) | HolidaysTaken (Sum of Holidays) 
20    |        19 |  1 

我能夠得到所有三列,如果我不狀態狀態 - 這裏是我得到的最接近的

SELECT 
IFNULL(SUM(IF( h.dateTo = h.dateFrom, 1, DATEDIFF(h.dateTo, h.dateFrom))), 0) AS holidaysTaken, 
IFNULL(us.HolidaysAllowed - (SUM( IF( h.DateTo = h.DateFrom, 1, DATEDIFF(h.DateTo, h.dateFrom)))), 0) AS holidaysLeftover, 
us.HolidaysAllowed 
FROM userSettings us 
LEFT JOIN holiday h 
ON h.userID = 1 
JOIN status s 
ON s.holidayID = h.holidayID AND s.statusID = 1 
WHERE 
us.userID = 1 
GROUP BY h.userID; 

主要問題是,如果沒有statusID爲2的節假日,則結果列1 & 2爲0(這是正確的),但列3(HolidaysAllowed)爲NULL(不正確,因爲它總是需要返回值表UserSettings)。上面的查詢只有當有至少一條記錄(假期)具有正確的狀態時才返回正確的響應......我做錯了什麼? :)

它只是驅使我堅果:)預先感謝任何幫助!非常感激!

UPDATE

謝謝大家誰評論...該預期的結果如下 把那有狀態的所有假期= 1(即接受),然後計算假期的統計數據,防止讓假期。即在總

20天,1個假期接受= 19天的時間採取

再次感謝

+0

你可以張貼一些示例數據和所需的O/P – Teja 2012-04-28 20:49:07

+0

@Vutukuri - 感謝您的意見。 ..我已經更新了我的問題。 Siva ... statusID可以有n種可能性。 – Stevanicus 2012-04-28 22:02:29

+0

週末的日子呢?我們應該假設週六/週日不計數? – 2012-04-28 22:15:21

回答

3
SELECT u.userID, u.HolidaysAllowed, 
u.holidaysAllowed - 
COALESCE( 
    (SELECT SUM(DATEDIFF(h1.dateTo, h1.dateFrom) + 1) 
     FROM holiday h1 
     INNER JOIN status s1 
     ON s1.holidayID = h1.holidayID 
     WHERE h1.userID = u.userID 
     AND s1.statusID = 1 
    ), 0) AS HolidaysLeft, 
COALESCE( 
    (SELECT SUM(DATEDIFF(h2.dateTo, h2.dateFrom) + 1) 
     FROM holiday h2 
     INNER JOIN status s2 
     ON s2.holidayID = h2.holidayID 
     WHERE h2.userID = u.userID 
     AND s2.statusID = 1 
    ), 0) AS HolidaysTaken 
FROM userSettings u 
; 
+1

這個查詢假設每個從/在節假日表中定義的持續時間包括工作日,而不是週末,所以兩個星期的假期需要被定義爲一對M-F假期。它還假定在過去的報告期間沒有假期記錄,例如去年。 – 2012-04-28 22:31:34

+0

感謝您的工作,如治療 – Stevanicus 2012-04-29 11:28:24

0
SELECT B.HolidaysAllowed AS HolidaysAllowed, 
     B.HolidaysAllowed-A.HolidaysTaken AS HolidaysLeft, 
     A.HolidaysTaken AS HolidaysTaken 
FROM 
(
SELECT A.userID,SUM(CASE WHEN DATEDIFF(A.dateTo,A.dateFom)=0 
          THEN 1 
          ELSE DATEDIFF(A.dateTo,A.dateFom) 
        ) AS HolidaysTaken 
FROM Holiday A,Status B 
WHERE A.holidayID = B.holidayID 
    AND A.statusText='accepted' 
GROUP BY useID 
) A, 
UserSettings B 
WHERE A.userID = B.userID; 
+2

現在的這個查詢實際上不如問題中發佈的原始版本正確。它不會檢查狀態表以確定假日是接受還是拒絕,它不會正確計算單日假期,也不會處理尚未使用假期的員工將遇到的NULL。 – 2012-04-28 22:27:57

+0

我希望這將有助於@Fred索博特卡...請檢查... – Teja 2012-04-29 05:00:55

+0

它仍然不正確。 DATEDIFF本身不能用於計算假期所涵蓋的天數,因爲DATEDIFF從未在其答案中包含第一天。原始問題要求將週一至週五的假期報告爲五天,而不是DATEDIFF在您從週五日期減去週一的日期後給予您的四天期限。 – 2012-04-29 06:10:06

2

下面的查詢不採取週末考慮。

Click here to view the demo in SQL Fiddle.

腳本

CREATE TABLE Holiday 
(  
     holidayid INT   NOT NULL AUTO_INCREMENT 
    , userid  VARCHAR(20) NOT NULL 
    , dateFrom DATETIME NOT NULL 
    , dateTo  DATETIME NOT NULL 
    , PRIMARY KEY(holidayid) 
); 

CREATE TABLE Status 
(  
     id   INT   NOT NULL AUTO_INCREMENT 
    , holidayid INT   NOT NULL 
    , statusid INT   NOT NULL 
    , PRIMARY KEY(id) 
); 

CREATE TABLE UserSettings 
(  
     id    INT  NOT NULL AUTO_INCREMENT 
    , userid   INT  NOT NULL 
    , HolidaysAllowed INT  NOT NULL 
    , PRIMARY KEY(id) 
); 

INSERT INTO Holiday (userid, dateFrom, dateTo) VALUES 
    (1, '2012-04-01', '2012-04-03'), 
    (2, '2012-04-04', '2012-04-05'), 
    (2, '2012-04-07', '2012-04-09'), 
    (3, '2012-04-09', '2012-04-12'), 
    (3, '2012-04-16', '2012-04-16'), 
    (1, '2012-04-19', '2012-04-22'); 

INSERT INTO Status (holidayid, statusid) VALUES 
    (1, 2), 
    (2, 1), 
    (3, 1), 
    (4, 1), 
    (5, 2), 
    (6, 2); 

INSERT INTO UserSettings (userid, HolidaysAllowed) VALUES 
    (1, 5), 
    (2, 10), 
    (3, 7), 
    (4, 6); 


SELECT u.userid 
    , u.HolidaysAllowed 
    , u.HolidaysAllowed - COALESCE(hol.HolidaysTaken, 0) AS HolidaysLeft 
    , COALESCE(hol.HolidaysTaken, 0) AS HolidaysTaken 
FROM 
(
    SELECT   h.userid 
       , ABS(SUM(
         CASE 
         WHEN statusid = 1 THEN DATEDIFF(dateTo, dateFrom) + 1 
         ELSE 0 END 
        )) HolidaysTaken 

    FROM   UserSettings us 
    LEFT OUTER JOIN Holiday   h 
    ON    us.userid  = h.userid 
    LEFT OUTER JOIN Status   s 
    ON    s.holidayid  = h.holidayid 
    GROUP BY  h.userid 
)     hol 
RIGHT OUTER JOIN UserSettings u 
ON     u.userid = hol.userid; 

輸出

USERID HOLIDAYSALLOWED HOLIDAYSLEFT HOLIDAYSTAKEN 
------ --------------- ------------ ------------- 
1    5    5   0 
2   10    5   5 
3    7    3   4 
4    6    6   0 
+0

謝謝你的回答 – Stevanicus 2012-04-29 13:27:06