SQL多表关联查询统计uid出现次数并保留其他返回字段
实现方案
要在保留全部原有明细记录、不改变返回行数的前提下新增每个uid的总次数字段,核心是避免普通聚合函数折叠行的问题,以下两种方案都可以满足需求:
方案1:窗口函数实现(推荐)
使用分区窗口函数可以直接按uid分组计算计数,同时保留所有明细行,不需要改动你原有查询的关联、过滤、去重逻辑,修改后的SQL如下:
SELECT DISTINCT a.uid AS uid, COUNT(a.uid) OVER (PARTITION BY a.uid) AS uid_count, a.creation_date AS creation_date, a.activity_date AS activity_date, b.feature1 AS feature1, -- 建议补全表别名,避免同名字段歧义 b.feature2 AS feature2, c.feature3 AS feature3 FROM table a INNER JOIN table b ON a.uid = b.uid INNER JOIN table c ON c.uid = a.uid WHERE *certain conditions* GROUP BY 1,2,3,4,5,6,7
说明:你原SQL中FROM后包裹三表关联的括号是多余的,已直接移除,不影响执行逻辑。窗口函数的计数是基于去重后的最终结果集计算的,同一个uid对应的所有明细行都会返回相同的总计数,完全匹配你需要的输出格式。
方案2:CTE预统计关联(兼容老版本数据库)
如果你使用的SQL引擎版本过低不支持窗口函数,可以先通过CTE保留原查询的全部结果,预计算每个uid的计数后再关联回明细,写法如下:
WITH base_detail AS ( -- 此处完全复用你原有查询逻辑,不需要做任何修改 SELECT DISTINCT a.uid AS uid, a.creation_date as creation_date, a.activity_date as activity_date, feature1 as feature1, feature2 as feature2, feature3 as feature3 FROM table a INNER JOIN table b ON a.uid = b.uid INNER JOIN table c ON c.uid = a.uid WHERE *certain conditions* GROUP BY 1,2,3,4,5,6 ) SELECT d.uid, cnt.uid_count, d.creation_date, d.activity_date, d.feature1, d.feature2, d.feature3 FROM base_detail d INNER JOIN ( SELECT uid, COUNT(1) AS uid_count FROM base_detail GROUP BY uid ) cnt ON d.uid = cnt.uid
原写法问题说明
直接在SELECT中加普通count(uid)配合GROUP BY会改变返回行数,是因为普通聚合函数会按照GROUP BY指定的粒度将多行折叠为单行返回;而窗口函数是按分区规则计算统计值后附加到每一行,不会对原结果的行做折叠,正好匹配你的需求。
另外你原SQL中feature1/feature2/feature3字段没有指定所属表别名,三表关联时如果存在同名字段会触发字段歧义报错,建议补全对应的表前缀。
内容的提问来源于stack exchange,提问作者Nata
相关产品推荐
相关产品推荐

