You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

SQL按条件过滤博客时保留全量关联分类聚合数据的方法

问题原因

把分类过滤条件直接写在WHERE子句会在分组聚合前剔除所有不匹配条件的关联行,最终聚合时只能拿到命中过滤规则的单个分类,无法返回博客绑定的全部分类。

最优实现方案

推荐用EXISTS子查询单独做过滤判断,完全不影响主查询的关联聚合逻辑,性能表现最好:

select b.id, b.domain, coalesce( array_agg(bc.name) 
    filter (where bc.id is not null), '{}' ) as cats
from blog b
left join blog_to_blog_category bt on bt.blog_id = b.id
left join blog_category bc on bc.id = bt.blog_category_id
where exists (
    select 1
    from blog_to_blog_category bt_filter
    join blog_category bc_filter 
        on bc_filter.id = bt_filter.blog_category_id
    where bt_filter.blog_id = b.id
      and bc_filter.name = 'marketing'
)
group by b.id;

逻辑说明

  • EXISTS子查询仅负责判断当前博客是否绑定了marketing分类,不会修改主查询关联返回的结果集
  • 主查询的左连和聚合逻辑和全量查询博客的逻辑完全一致,因此可以正常返回博客关联的所有分类
  • 基于示例数据执行以上查询,只会返回匹配分类的id=1的博客one.com,对应的cats字段值为{business,marketing,misc},完全符合预期。
极简写法(适合小数据量场景)

如果追求代码简洁,也可以在分组后用HAVING做过滤,不需要额外写关联子查询:

select b.id, b.domain, coalesce( array_agg(bc.name) 
    filter (where bc.id is not null), '{}' ) as cats
from blog b
left join blog_to_blog_category bt on bt.blog_id = b.id
left join blog_category bc on bc.id = bt.blog_category_id
group by b.id
having 'marketing' = any(coalesce( array_agg(bc.name) 
    filter (where bc.id is not null), '{}' ));

该写法的缺点是需要先对所有博客做全量关联和聚合,再过滤掉不满足条件的记录,数据量大时性能比EXISTS方案差。


内容的提问来源于stack exchange,提问作者Guerrilla

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.27 13:48:23