令我感到困惑的是,谷歌没有多少帮助我,希望有人能指出我正确的方向。
请注意,为了简化问题,我省略了表中与问题无关的一些字段。
联系人
contact_id
name
email
contact_uuids
uuid
contact_id
visitor_activity
uuid
event
contact_communications
comm_id
contact_id
employee_id
查询
SELECT
`c`.*,
(SELECT COUNT(`log_id`) FROM `contact_communications` `cc` WHERE `cc`.`contact_id` = `c`.`contact_id`) as `num_comms`,
(SELECT MAX(`date`) FROM `contact_communications` `cc` WHERE `cc`.`contact_id` = `c`.`contact_id`) as `latest_date`,
(SELECT MIN(`date`) FROM `contact_communications` `cc` WHERE `cc`.`contact_id` = `c`.`contact_id`) as `first_date`,
(SELECT COUNT(`vaid`) FROM `visitor_activity` `va` WHERE `va`.`uuid` = `cu`.`uuid`) as `num_act`
FROM `contacts` `c`
LEFT JOIN `contact_uuids` `cu` ON `c`.`contact_id` = `cu`.`contact_id`
GROUP BY `c`.`contact_id`
ORDER BY `c`.`name` ASC
某些联系人有多个UUID(超过20或30)。
当我执行不带GROUP BY语句的查询时,我得到了我期望的结果 - 为该联系人存在的每个UUID返回一行,并使用正确的“num_comms”和“num_act”数字。
但是当我添加GROUP BY语句时,“num_comms”比预期的要小很多,“num_act”只返回没有GROUP BY语句的第一行的值。
我尝试在子查询中执行“WHERE NOT IN”,但这只会使服务器崩溃,因为它太强烈了。
那么 - 如何让这个从LEFT JOIN中添加所有COUNT值而不只是返回第一个值?
此外,如果有人可以帮助我优化这一点,那就太棒了。
答案 0 :(得分:1)
两个问题:
GROUP BY c
。contact_id
不包含所有非汇总列。这是一个MySQL扩展。你得到的是除contact_id
JOIN增加了混乱。您对visitor_activity的唯一用途是COUNT(*)。但这没有意义,因为它仅限于一个UUID,而行仅限于一个contact_id。重新考虑其目的。
删除此行:
(SELECT COUNT(`vaid`) FROM `visitor_activity` `va` WHERE `va`.`uuid` = `cu`.`uuid`) as `num_act`
其余的可以正常工作。
我将继续假设您希望与一个contact_id关联的所有uuids都包含visitor_activity中所有行的COUNT。
看看是否:
( SELECT COUNT(*)
FROM `contacts` c2
JOIN `visitor_activity` USING(uuid)
WHERE c2.contact_id = c.contact_id as `num_act` ) AS num_act
将适用于最后一个子查询。同时,删除JOIN:
LEFT JOIN `contact_uuids` `cu` ON `c`.`contact_id` = `cu`.`contact_id`
现在,回到另一个问题(GROUP BY的非标准用法)。假设contact_id是PRIMARY KEY,那么只需删除
即可GROUP BY `c`.`contact_id`