0

也许有人可以对我一整天都在与之抗争的声明有所了解:)

我有 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

用户设置

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 返回值) . 仅当至少有 1 条记录(假期)具有正确的状态时,上述查询才会返回正确的响应......我做错了什么?:)

它只是让我发疯:)提前感谢您的帮助!非常感激!

更新

感谢所有评论的人......预期结果如下获取所有状态= 1(即接受)的假期,然后根据允许的假期计算假期统计数据。IE

总共 20 天,接受 1 个假期 = 还剩 19 天

再次感谢

4

3 回答 3

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
;
于 2012-04-28T22:12:08.137 回答
2

以下查询不考虑周末。

单击此处查看 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
于 2012-04-28T22:29:46.867 回答
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;
于 2012-04-28T22:11:13.447 回答