- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
假设我有以下假设的数据结构:
create table "country"
(
country_id integer,
country_name varchar(50),
continent varchar(50),
constraint country_pkey primary key (country_id)
);
create table "person"
(
person_id integer,
person_name varchar(100),
country_id integer,
constraint person_pkey primary key (person_id)
);
create table "event"
(
event_id integer,
event_desc varchar(100),
country_id integer,
constraint event_pkey primary key (event_id)
);
我想查询每个国家的人物和事件的行数。我决定使用子查询。
select c.country_name, sum(sub1.person_count) as person_count, sum(sub2.event_count) as event_count
from
"country" c
left join (select country_id, count(*) as person_count from "person" group by country_id) sub1
on (c.country_id=sub1.country_id)
left join (select country_id, count(*) as event_count from "event" group by country_id) sub2
on (c.country_id=sub2.country_id)
group by c.country_name
我知道你可以通过在字段列表中使用 select 语句来做到这一点,但是使用子查询的好处是我可以更灵活地更改 SQL 使其汇总并使用另一个字段。比方说,如果我将查询更改为按大陆显示它,那么只需将字段“c.country_name”替换为“c.continent”即可。
我的问题是关于过滤。如果我们像这样添加一个 where 子句:
select c.country_name,
sum(sub1.person_count) as person_count,
sum(sub2.event_count) as event_count
from
"country" c
left join (select country_id, count(*) as person_count from "person" group by country_id) sub1
on (c.country_id=sub1.country_id)
left join (select country_id, count(*) as event_count from "event" group by country_id) sub2
on (c.country_id=sub2.country_id)
where c.country_name='UNITED STATES'
group by c.country_name
子查询似乎仍然对所有国家/地区执行计数。假设 person 和 event 表很大,并且我已经在所有表的 country_id 上建立了索引。真的很慢。数据库不应该只执行被过滤国家的子查询吗?我是否必须为每个子查询重新创建国家/地区过滤器(这非常乏味并且代码不易修改)?顺便说一句,我同时使用 PostgreSQL 8.3 和 9.0,但我猜其他数据库中也会发生同样的情况。
最佳答案
Shouldn't the database only execute the subqueries for the country that was filtered?
没有。在像您这样的查询中,第一步似乎是从 FROM 子句中的所有表构造函数构建一个工作表。之后评估 WHERE 子句。
想象一下,如果 sub1 和 sub2 都是基表而不是子查询,您会怎么做。它们都有两列,每个 country_id 都有一行。如果你想 JOIN 所有的行,你会这样写。
from
"country" c
left join sub1 on (c.country_id=sub1.country_id)
left join sub2 on (c.country_id=sub2.country_id)
但是如果你想在一行上加入 JOIN,你会写一些与此等效的东西。
from
"country" c
left join (select * from sub1 where country_id = ?)
on (c.country_id=sub1.country_id)
left join (select * from sub2 where country_id = ?)
on (c.country_id=sub2.country_id)
帮助开发早期 SQL 标准的 Joe Celko 经常撰写关于 how SQL's order of evaluation appears 的文章在 Usenet 上。
关于sql - 为带有子查询的查询优化 SQL "Where"子句,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7924093/
我是一名优秀的程序员,十分优秀!