我在优化IS NULL
检查联接表时遇到了一个具有挑战性的问题。
在以下查询中,您会看到我RIGHT JOIN
calendar
表。只要我不检查calendar.time
is null
,查询就能完美运行。
select `teams`.`name` as `label`, `teams`.`id` as `id`, count(`teams`.`id`) as value
from `likes`
right join `calendar` on `calendar_id` = `calendar`.`id`
left join `profile_team` on `likes`.`profile_id` = `profile_team`.`profile_id`
right join `teams` on `profile_team`.`team_id` = `teams`.`id`
where (
`calendar`.`time` between '2015-02-14' and '2015-04-14'
or `calendar`.`time` is null
)
group by `teams`.`id`;
小提琴:http://sqlfiddle.com/#!9/200c0/7
查询的想法是返回teams
的每一行,即使likes
没有相关的行。 likes
和teams
通过likes.profile_id
到profile_team.profile_id
和profile_team.team_id
与teams.id
相关联。
calendar
已加入,因为它包含按时间过滤数据集的参考点。
感谢您的帮助。
修改:EXPLAIN
输出:
使用IS NULL
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
|----|-------------|--------------|--------|---------------------|---------------------|---------|------------------------------|------|--------------------------|
| 1 | SIMPLE | teams | index | PRIMARY | PRIMARY | 4 | (null) | 1 | (null) |
| 1 | SIMPLE | profile_team | index | profile_team_unique | profile_team_unique | 8 | (null) | 1 | Using where; Using index |
| 1 | SIMPLE | likes | ALL | calendar_id | (null) | (null) | (null) | 8 | Using where |
| 1 | SIMPLE | calendar | eq_ref | PRIMARY | PRIMARY | 4 | db_9_200c0.likes.calendar_id | 1 | Using where |
没有IS NULL
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
|----|-------------|--------------|--------|---------------------|---------------------|---------|---------------------------------|------|-----------------------------------------------------------|
| 1 | SIMPLE | calendar | range | PRIMARY,time | time | 4 | (null) | 1 | Using where; Using index; Using temporary; Using filesort |
| 1 | SIMPLE | likes | ref | calendar_id | calendar_id | 5 | db_9_200c0.calendar.id | 1 | (null) |
| 1 | SIMPLE | profile_team | ref | profile_team_unique | profile_team_unique | 4 | db_9_200c0.likes.profile_id | 1 | Using where; Using index |
| 1 | SIMPLE | teams | eq_ref | PRIMARY | PRIMARY | 4 | db_9_200c0.profile_team.team_id | 1 | Using where |
答案 0 :(得分:0)
请尝试此查询:
SELECT
`teams`.`name` as `label`, `teams`.`id` as `id`
FROM
`teams`
LEFT JOIN
`profile_team` ON `teams`.`id` = `profile_team`.`team_id`
LEFT JOIN
`likes` ON `profile_team`.`profile_id` = `likes`.`profile_id`
LEFT JOIN
`calendar` ON `likes`.`calendar_id` = `calendar`.`id`
AND
`calendar`.`time` BETWEEN '2015-02-14' AND '2015-04-14'
UNION ALL
SELECT
`teams`.`name` as `label`, `teams`.`id` as `id`
FROM
`teams`
LEFT JOIN
`profile_team` ON `teams`.`id` = `profile_team`.`team_id`
LEFT JOIN
`likes` ON `profile_team`.`profile_id` = `likes`.`profile_id`
LEFT JOIN
`calendar` ON `likes`.`calendar_id` = `calendar`.`id`
AND
IFNULL(`calendar`.`time`, 0) = 0
我现在无法测试;)。
我在做什么?
teams
)制作联接顺序,所以我只有LEFT JOIN
。WHERE
时删除JOIN
。OR
替换UNION ALL
以获得更好的效果。IFNULL
代替IS NULL
。