有效使用子查询?

时间:2011-07-14 23:16:09

标签: mysql sql

我想知道是否有人可以指出以下查询的潜在问题,或者是否有更好的替代方案

从用户列表中我想要返回所有没有指定所有user_profile选项的用户或者没有至少有一个首选项设置为1的用户。以下查询似乎可以正常工作。

SELECT DISTINCT(c.id) FROM user c
                 WHERE c.id IN (901,907)
                 AND 
        ((SELECT COUNT(id) FROM user_profile
                          WHERE option_id in (747,749) AND user_id=c.id) < 2
         OR
        (SELECT COUNT(id) FROM user_profile
                          WHERE option_id in (747,749) AND user_id=c.id AND preference = 1) != 1
         )

表格定义

CREATE TABLE `user_profile` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `option_id` int(11) NOT NULL,
  `user_id` int(11) NOT NULL,
  `preference` decimal(10,2) DEFAULT '0.00',
  `created_date` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
  PRIMARY KEY (`id`),
  KEY `user_profile_user_id` (`user_id`),
  KEY `user_profile_option_id` (`option_id`),
  CONSTRAINT `user_profile_user_id` FOREIGN KEY (`user_id`) REFERENCES `user` (`id`),
  CONSTRAINT `user_profile_option_id` FOREIGN KEY (`option_id`) REFERENCES `option` (`id`),
) ENGINE=InnoDB;

2 个答案:

答案 0 :(得分:3)

将2个谓词连接到单个查询中,该查询将执行单个表查找。

SELECT c.id
FROM user c LEFT JOIN user_profile p 
     ON c.id = p.user_id
     AND p.option_id in (747, 749)
WHERE user_id IN (901,907)
GROUP BY c.id
HAVING COUNT(p.id) < 2 OR SUM(p.preference = 1) != 1

答案 1 :(得分:1)

只要你有基于PK的条件c.id IN (901,907) - 它就不会有问题。

因为mysql最初会按id过滤,之后会执行最多2条记录的嵌套查询。