2011-06-23 27 views
5

Vì vậy, các schema bảng sản xuất là như thế này:MySQL Nhóm OR và AND khoản

producer_id = int PK 
producer_name = varchar 
is_restaurant = boolean 
is_farm = boolean 
is_distributor = boolean 

và tôi muốn có một truy vấn mà thực hiện điều này:

chọn tất cả các nhà sản xuất có producer_id là trong (11.895 , 11976, 11457) là trang trại, nhà hàng hoặc nhà phân phối

Tôi có điều này:

SELECT `pd`.`producer_id` AS producer_id, `pd`.`producer` AS producer, `pd`.`is_restaurant`, `pd`.`is_restaurant_chain`, `pd`.`is_farm`, `pd`.`is_farmers_market`, `pd`.`is_distributor`, `pd`.`is_manufacture`, `ad`.`address_id`, `ad`.`address`, `ad`.`state_id`, `ad`.`city`, `ad`.`city_id`, `ad`.`country_id`, `ad`.`zipcode`, `ad`.`latitude`, `ad`.`longitude`, `cu`.`custom_url` AS custom_url 
FROM (`producer` AS pd) 
JOIN `address` AS ad ON `pd`.`producer_id`=`ad`.`producer_id` 
LEFT JOIN `custom_url` AS cu ON `cu`.`producer_id`=`pd`.`producer_id` 
WHERE `is_farm` = 1 
OR `is_distributor` = 1 
OR `is_restaurant` = 1 
AND `pd`.`producer_id` IN ('181176', '181180', '176080', '5') 
GROUP BY `ad`.`address_id` 
LIMIT 10 

nhưng truy vấn chỉ áp dụng điều kiện WHERE cho is_farm, is_distributor và is_restaurant và không áp dụng mệnh đề AND cho producer_id.

Tôi đã tự hỏi liệu mình có thể sử dụng truy vấn phụ để làm "là nhà hàng hoặc nhà phân phối hay nhà hàng" và chỉ cần chèn nó vào truy vấn với mệnh đề AND.

Tôi có thể làm gì để giải quyết vấn đề này?

Trả lời

10

Vấn đề của bạn là trong SQL, AND được ưu tiên hơn OR, vì vậy bạn chỉ cần dấu ngoặc:

SELECT `pd`.`producer_id` AS producer_id, `pd`.`producer` AS producer, `pd`.`is_restaurant`, `pd`.`is_restaurant_chain`, `pd`.`is_farm`, `pd`.`is_farmers_market`, `pd`.`is_distributor`, `pd`.`is_manufacture`, `ad`.`address_id`, `ad`.`address`, `ad`.`state_id`, `ad`.`city`, `ad`.`city_id`, `ad`.`country_id`, `ad`.`zipcode`, `ad`.`latitude`, `ad`.`longitude`, `cu`.`custom_url` AS custom_url 
FROM (`producer` AS pd) 
JOIN `address` AS ad ON `pd`.`producer_id`=`ad`.`producer_id` 
LEFT JOIN `custom_url` AS cu ON `cu`.`producer_id`=`pd`.`producer_id` 
WHERE (`is_farm` = 1 -- NOTE: Opening bracket to bracket up your OR terms together 
OR `is_distributor` = 1 
OR `is_restaurant` = 1) -- NOTE: Closing bracket 
AND `pd`.`producer_id` IN ('181176', '181180', '176080', '5') 
GROUP BY `ad`.`address_id` 
LIMIT 10 

Hệ luỵ:

Trong SQL A OR B OR C AND D được phân tách như (A OR (B OR (C AND D))). Áp dụng các dấu ngoặc vuông sẽ sửa lỗi phổ biến này, tức là (A OR B OR C) AND D.

Hãy nhớ: Khi trộn các điều khoản ANDOR, hãy luôn sử dụng dấu ngoặc!

+0

hm ... bất kỳ ý tưởng làm thế nào tôi có thể làm công việc này với CI của Active Record? – yretuta

+0

nếu bạn không có quyền kiểm soát cú pháp SQL, hãy thử tạo chế độ xem có cột bổ sung: 'create view producer_plus như select *, is_restaurant hoặc is_farm hoặc is_distributor là is_producer từ nhà sản xuất'. Bạn sẽ vẫn có thể cập nhật nó (vì nó không phải là một tham gia), nhưng bạn sẽ không thể ghi vào cột được tính toán của khóa học – Bohemian

+0

Câu trả lời này gần như đã bị bỏ qua một chút của tôi, trên thực tế 'AND' được ưu tiên là phổ biến trong những ngôn ngữ khác. – hlev

2

này nên làm như lừa:

SELECT `pd`.`producer_id` AS producer_id, `pd`.`producer` AS producer, `pd`.`is_restaurant`, `pd`.`is_restaurant_chain`, `pd`.`is_farm`, `pd`.`is_farmers_market`, `pd`.`is_distributor`, `pd`.`is_manufacture`, `ad`.`address_id`, `ad`.`address`, `ad`.`state_id`, `ad`.`city`, `ad`.`city_id`, `ad`.`country_id`, `ad`.`zipcode`, `ad`.`latitude`, `ad`.`longitude`, `cu`.`custom_url` AS custom_url 
FROM (`producer` AS pd) 
JOIN `address` AS ad ON `pd`.`producer_id`=`ad`.`producer_id` 
LEFT JOIN `custom_url` AS cu ON `cu`.`producer_id`=`pd`.`producer_id` 
WHERE `pd`.`producer_id` IN ('181176', '181180', '176080', '5') 
AND (`is_distributor` = 1 OR `is_restaurant` = 1 OR `is_farm` = 1) 
GROUP BY `ad`.`address_id` 
LIMIT 10