简体   繁体   中英

Stored procedure returning the wrong value?

I have a stored procedure that check holidays that are booked off in my database and it should not take into account holidays with a status of 'Declined' or 'Cancelled', yet o have only one record in my database which has a status of declined but this select statement returns 1?

        SELECT COUNT(*) JobRoleID
        FROM        Employees
        RIGHT JOIN  Holidays
        ON          Employees.ID = Holidays.EmployeeID
        WHERE       Holidays.Status <> 'Declined' AND Holidays.Status <> 'Cancelled'
        AND        (Holidays.Startdate <= '2014/04/28' AND Holidays.Enddate >= '2014/04/30')
        OR         (Holidays.Startdate >= '2014/04/28' AND Holidays.Enddate <= '2014/04/30') 
        OR         (Holidays.Startdate <= '2014/04/30' AND Holidays.Enddate >= '2014/04/30') 
        OR         (Holidays.Startdate <= '2014/04/28' AND Holidays.Enddate >= '2014/04/28') 
        OR         (Holidays.StartDate = '2014/04/28' AND Holidays.EndDate = '2014/04/30')

Operator precedence needs to be taken into consideration here.

Not -->  AND --> OR 

Not takes precedence over AND , AND takes precedence over OR. With these nested ANDs and ORs it is always better to put them in paranthesis.

WHERE       Holidays.[Status] <> 'Declined' AND Holidays.[Status] <> 'Cancelled'
AND    
    (       (Holidays.Startdate <= '2014/04/28' AND Holidays.Enddate >= '2014/04/30')
        OR  (Holidays.Startdate >= '2014/04/28' AND Holidays.Enddate <= '2014/04/30') 
        OR  (Holidays.Startdate <= '2014/04/30' AND Holidays.Enddate >= '2014/04/30') 
        OR  (Holidays.Startdate <= '2014/04/28' AND Holidays.Enddate >= '2014/04/28') 
        OR  (Holidays.StartDate = '2014/04/28' AND Holidays.EndDate = '2014/04/30')
    )

Also avoid using Sql server key words as your column names, if you do have some use square brackets [] around them when using them in your sql.

WHERE A AND B AND C OR D AND E OR F AND G

Is treated the same as

WHERE (A AND B AND C) OR (D AND E) OR (F AND G)

So if any of your date comparisons other than the first one are in fact true, then the entire WHERE clause is satisfied.

And, by the way, it looks like you're trying to find whether two date ranges overlap, and doing it in a very complex matter. You should only need to do two comparisons. Two date ranges overlap if:

  • The first range starts before the end of the second range, and
  • The second range starts before the end of the first range

So, something like:

SELECT COUNT(*) JobRoleID
    FROM        Employees
    RIGHT JOIN  Holidays
    ON          Employees.ID = Holidays.EmployeeID
    WHERE       Holidays.Status <> 'Declined' AND Holidays.Status <> 'Cancelled'
    AND    Holidays.StartDate <= '20140430' AND '20140428' <= Holidays.EndDate

Should be the equivalent of your multiple comparisons.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM