我有表A,B,C。表A链接到B,表A链接到C.我想加入3个表,找到B.cost的总和和C.clicks的总和。但是,它没有给我预期的值,当我选择没有group by的所有内容时,它显示重复的行。我期望B中的行值汇总为单个总和,并且C中的行值汇总为单个总和。
我的查询看起来像
select A.*, sum(B.cost), sum(C.clicks) from A
join B
left join C
group by A.id
having sum(cost) > 10
我尝试按B.a_id
和C.another_field_in_a
进行分组,但这不起作用。
这是一个DB小提琴,包含所有数据和完整查询:
注意sum字段是如何大于各个表的总和的?我希望总和相等,只包含表B和C的行一次。我也尝试添加distinct
,但这并没有帮助。
我正在使用Postgres。 (虽然这个小提琴设置为MySQL。)最后我想使用having
子句根据它们的总和来选择行。此查询将针对数百万行。
答案 0 :(得分:1)
如果我理解逻辑正确,问题是由两个连接引起的笛卡尔积。您的查询有点难以理解,但我认为使用相关子查询可以更好地处理意图:
select k.*,
(select sum(cost)
from ad_group_keyword_network n
where n.event_date >= '2015-12-27' and
n.ad_group_keyword_id = 1210802 and
k.id = n.ad_group_keyword_id
) as cost,
(select sum(clicks)
from keyword_click c
where (c.date is null or c.date >= '2015-12-27') and
k.keyword_id = c.keyword_id
) as clicks
from ad_group_keyword k
where k.status = 2 ;
Here是相应的SQL小提琴。
编辑:
子选择应该比未聚合数据上的group by
更快。但是,您需要正确的索引:ad_group_keyword_network(ad_group_keyword_id, ad_group_keyword_id, event_date, cost)
和keyword_click(keyword_id, date, clicks)
。
答案 1 :(得分:1)
我找到了这个(MySQL joining tables group by sum issue)并创建了一个像这样的查询
select *
from A
join (select B.a_id, sum(B.cost) as cost
from B
group by B.a_id) B on A.id = B.a_id
left join (select C.keyword_id, sum(C.clicks) as clicks
from C
group by C.keyword_id) C on A.keyword_id = C.keyword_id
group by A.id
having sum(cost) > 10
我不知道它是否有效。我不知道它是否比戈登的效率更高或更低。我跑了两个查询,这个看起来更快,27秒对2分35秒。这是一个小提琴:http://sqlfiddle.com/#!15/c61c74/10
答案 2 :(得分:1)
只需将第二个表的聚合分割为子查询,如下所示:
http://sqlfiddle.com/#!9/768745/27
select ad_group_keyword.*, SumCost, sum(keyword_click.clicks)
from ad_group_keyword
left join keyword_click on ad_group_keyword.keyword_id = keyword_click.keyword_id
left join (select ad_group_keyword.id, sum(cost) SumCost
from ad_group_keyword join ad_group_keyword_network on ad_group_keyword.id = ad_group_keyword_network.ad_group_keyword_id
where event_date >= '2015-12-27'
group by ad_group_keyword.id
having sum(cost) > 20
) Cost on Cost.id=ad_group_keyword.id
where
(keyword_click.date is null or keyword_click.date >= '2015-12-27')
and status = 2
group by ad_group_keyword.id