2011-06-23 16 views
5

lo tanto, el esquema de la tabla productor es así:MySQL Agrupación OR y cláusulas

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

y quiero una consulta que hace esto:

seleccionar todos los productores cuyas producer_id están en (11895 , 11976, 11457), que es ya sea una granja, un restaurante o un distribuidor

tengo esto:

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 

pero la consulta sólo se aplica a las condiciones donde por is_farm, is_distributor y is_restaurant y no se aplica la cláusula AND para producer_id.

Me preguntaba si podría usar una subconsulta para hacer "es un restaurante, un distribuidor o una granja" y simplemente insertarlo en la consulta con una cláusula AND.

¿Qué puedo hacer para solucionar esto?

Respuesta

10

Su problema es que en SQL, AND tiene prioridad sobre OR, por lo que sólo necesita paréntesis:

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 

Corolario:

En SQL A OR B OR C AND D se analiza como (A OR (B OR (C AND D))). La aplicación de corchetes corregirá este error común, es decir, (A OR B OR C) AND D.

Recuerde: Cuando mezcle AND y OR términos, utilice siempre corchetes.

+0

hm ... alguna idea de cómo puedo hacer este trabajo con CI de Active Record? – yretuta

+0

si no tiene control sobre la sintaxis SQL, intente crear una vista que tenga una columna adicional: 'create view producer_plus como select *, is_restaurant o is_farm o is_distributor como is_producer del productor'. Todavía podrá actualizarlo (porque no es una unión), pero no podrá escribir en la columna calculada del curso – Bohemian

+0

. Esta respuesta casi desvió mi atención un poco, de hecho 'Y' tiene prioridad como común en otros idiomas. – hlev

2

Esto debería hacer el truco:

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 
Cuestiones relacionadas