2016-06-20 18 views
17

Tôi có truy vấn sau đây:HOẶC mâu thuẫn giữa các điều kiện khác

SELECT * FROM `Contacts` 
WHERE `Zona` = '1' 
AND `Responsable` = '9' 
AND `AllowComercialVisit` = 'Call_Again' 
-- the problem are OR's -- 
OR `AllowComercialVisit` = 'Busy' 
OR `AllowComercialVisit` = 'Not_answered' 
-- the problem are OR's -- 
AND `DateRecall` <= '2016-06-20 13:04:52' 
AND `DateRecall` >= '2016-06-20 12:39:52' 
ORDER BY `DateRecall` ASC LIMIT 1 

Vấn đề là các truy vấn nên CHỈ cho thấy các hàng giữa đầu tiên và thứ hai 'DateRecall', nhưng trả lại tất cả các hàng với 'Call_Again', 'Busy' và 'Not_answered' mà không lọc ngày tháng.

Bất kỳ giải pháp nào sẽ được đánh giá cao!

+9

Không bao giờ, bao giờ hết, * bao giờ hết * trộn 'OR' với' AND' mà không sử dụng dấu ngoặc đơn để làm cho nhóm của bạn rõ ràng, bằng bất kỳ ngôn ngữ nào. Ngay cả khi nó không được yêu cầu nghiêm ngặt trong một số tình huống, không ai có thể tìm ra ý định của bạn mà không có chúng. – jpmc26

+2

Mặc dù tôi không đồng ý rằng "không ai có thể tìm ra ý định của bạn mà không có họ", tôi hoàn toàn đồng ý với việc luôn sử dụng dấu ngoặc đơn. Ngoại lệ duy nhất tôi thực hiện là khi bạn đang thực hiện chính xác một so sánh trong các ngôn ngữ hỗ trợ nó, như Python; trong tất cả các trường hợp khác, dấu ngoặc đơn không chỉ làm cho mã của bạn dễ đọc hơn, chúng còn bảo vệ bạn khỏi trật tự của các vấn đề hoạt động (và khác, khó định lượng các vấn đề hơn, như một số boolean quirks trong PHP không có ý nghĩa logic nhưng vẫn bị ngăn cản theo cách này). Đối với các truy vấn SQL, cũng xem xét các mức thụt đầu dòng cho sự rõ ràng làm tổ. – kungphu

Trả lời

47

Một đơn giản IN() sẽ giải quyết này:

SELECT * FROM `Contacts` 
WHERE `Zona` = '1' 
    AND `Responsable` = '9' 
    AND `AllowComercialVisit` IN ('Call_Again','Busy','Not_answered') 
    AND `DateRecall` BETWEEN '2016-06-20 12:39:52' 
         AND '2016-06-20 13:04:52' 
ORDER BY `DateRecall` ASC 
LIMIT 1 

Nói chung, AND có ưu tiên hơn OR, khi sử dụng OR hãy thử sử dụng dấu ngoặc đơn ->

WHERE COND1 AND COND2 AND (COND3 OR COND4) AND COND5 

Mà sẽ buộc tôi ưu hoa theo của bạn ưu tiên và không phải là mặc định.

+1

Bạn không thể sử dụng GIỮA để rút ngắn truy vấn? Tôi nhận ra nó không tạo sự khác biệt cho trình tối ưu hóa, nhưng tôi thấy nó dễ đọc hơn. – sfdcfox

12

Hãy thử truy vấn sau đây:

SELECT * FROM `Contacts` 
WHERE `Zona` = '1' 
AND `Responsable` = '9' 
AND (`AllowComercialVisit` = 'Call_Again' OR `AllowComercialVisit` = 'Busy' OR AllowComercialVisit` = 'Not_answered') 
AND `DateRecall` <= '2016-06-20 13:04:52' 
AND `DateRecall` >= '2016-06-20 12:39:52' 
ORDER BY `DateRecall` ASC 
LIMIT 1 

Chỉ vòm của OR với dấu ngoặc đơn.

7

Cố gắng nhóm OR báo cáo khi họ có liên quan đến cùng một cột, tức

SELECT * FROM `Contacts` 
WHERE `Zona` = '1' 
AND `Responsable` = '9' 
AND (`AllowComercialVisit` = 'Call_Again' 
OR `AllowComercialVisit` = 'Busy' 
OR `AllowComercialVisit` = 'Not_answered') 
AND `DateRecall` <= '2016-06-20 13:04:52' 
AND `DateRecall` >= '2016-06-20 12:39:52' 
ORDER BY `DateRecall` ASC LIMIT 1 
0

Bạn có thể sử dụng câu lệnh IN() thay vì OR s:

SELECT * FROM `Contacts` 
WHERE `Zona` = '1' 
    AND `Responsable` = '9' 
    AND `AllowComercialVisit` IN('Call_Again','Busy','Not_answered') 
    AND `DateRecall` <= '2016-06-20 13:04:52' 
    AND `DateRecall` >= '2016-06-20 12:39:52' 
    ORDER BY `DateRecall` ASC LIMIT 1 
Các vấn đề liên quan