
文档教程知识库【免费下载链接】til:memo: Today I Learned项目地址https://gitcode.com/gh_mirrors/ti/til点击查看免费下载本指南以仓库文档 postgres/count-records-by-type.md 为核心讲解如何利用group by与聚合函数count(*)对带有类型列的数据库表进行分组统计。读完本文你将掌握按某列分类计数这一最常用的数据探索手段并进一步学会排序输出、处理 NULL 分组、按表达式分组、使用having过滤聚合结果等进阶写法轻松应用于报表统计、去重排查与数据质量分析等场景。一、核心问题如何按类型统计记录数在实际业务表中我们经常会有某种类型列type column——例如订单表里的支付方式、日志表里的日志级别、商品表里的分类、宠物图鉴里的属性。最常见的需求是这张表里每一种类型各有多少条记录答案非常简单借助group by把记录按类型归组再用聚合函数count(*)统计每一组的行数。原文档给出了一个经典的pokemon宝可梦示例 select type, count(*) from pokemon group by type; type | count ----------------- fire | 10 water | 4 plant | 7 psychic | 3 rock | 12这里group by type会将pokemon表中所有type相同的行合并为一个分组随后count(*)对每个分组内的行数进行计数。最终结果每一行代表一种type及其对应的记录条数是典型的一对多分组统计。与之完全同构的另一个例子来自仓库文档 postgres/count-how-many-records-there-are-of-each-type.md一张books表通过status列区分书籍处于published、review、draft等状态同样一条查询即可得到各状态的书目数量 select status, count(*) from books group by status; status | count ------------------ ø | 123 published | 611 draft | 364 review | 239 (4 rows)可以看到两种写法完全一致select 类型列, count(*) from 表名 group by 类型列就是按类型统计记录数的标准模板可以套用在任何带有枚举、状态或分类性质的列上。二、语法要点SELECT 中的非聚合列必须出现在 GROUP BY 中当select列表中同时出现普通列和聚合函数如count(*)、sum、avg时PostgreSQL 要求所有非聚合的普通列都必须出现在group by子句中否则会直接报错。也就是说select type, count(*) from pokemon group by type;中type既出现在投影列又出现在分组键二者保持一致查询才能成立。如果只写select type, count(*) from pokemon;省略group byPostgreSQL 会抛出错误提示column pokemon.type must appear in the GROUP BY clause or be used in an aggregate function。这正是group by的语义保证——每一个输出行对应一个分组而非对应单条记录。三、进阶一按计数降序排列让结果更有秩序默认情况下group by输出的分组顺序并不保证稳定。仓库文档 postgres/count-how-many-records-there-are-of-each-type.md 指出可以通过在查询末尾追加order by让输出按计数值排序从而一眼看出数量最多的类型 select status, count(*) from books group by status order by 2 desc; status | count ------------------ published | 611 draft | 364 review | 239 ø | 123 (4 rows)这里的order by 2用的是**位置索引argument index**写法。PostgreSQL 中select列表里的每个参数都拥有一个从 1 开始的索引可以在order by和group by中直接引用。所以order by 2等价于order by count(*)desc表示从高到低降序排列。这种技巧在 postgres/use-argument-indexes.md 中有更完整的介绍——例如select id, updated_at from posts order by 2;就等价于order by updated_at。该文档还给出了一个同时使用位置索引完成按类型分组 按计数降序的组合示例select type, count(*) from transaction group by 1 order by 2 desc;其中group by 1引用typeorder by 2引用count(*)。在列名较长或聚合表达式复杂时位置索引能让查询更紧凑不过若调整了select列顺序位置索引会随之改变需谨慎使用。四、进阶二NULL 类型也自成一组当类型列没有not null约束时group by会把所有NULL值的记录归入同一个分组。上面books示例输出中的ø一行就是status为 NULL 的记录组共计 123 条。这是group by的既定行为NULL 作为一个特殊的分组键存在。这一点对实际业务很有意义——统计结果中出现的 NULL 分组往往意味着数据录入不完整或存在脏数据可以据此定位需要补全或清洗的记录而不仅仅是把它们忽略掉。五、进阶三按函数/表达式结果分组扩展统计维度group by并不局限于直接按某一列分组。仓库文档 postgres/group-by-the-result-of-a-function-call.md 展示了按表达式结果分组的做法。假设products表的identifier列前三个字母代表商品分类可以这样按分类统计select substring(identifier from 1 for 3), count(*) from products group by substring(identifier from 1 for 3);需要注意group by中出现的表达式必须与select列表中的表达式逐字一致PostgreSQL 不支持用别名alias引用分组表达式。这种写法把按类型计数推广到了按类型的派生特征计数例如按日期截断到月份统计订单数group by date_trunc(month, created_at)、按首字母统计联系人数量等非常适合数据探索。六、进阶四用 HAVING 过滤分组结果如果你想要的不是全部分组而是计数满足某种条件的类型则需要使用having子句。因为聚合函数如count不能在where中使用——where作用于分组之前的单行而聚合结果要等分组完成后才产生。仓库文档 postgres/find-records-that-contain-duplicate-values.md 用它来查找重复邮箱select email, count(*) from mailing_list group by email having count(*) 1 order by email;这个查询按email分组having count(*) 1仅保留出现次数大于 1 的分组从而精确筛出重复记录。同样的思路可以套用到类型统计上例如只想看记录数超过某个阈值的类型只需把having条件改为having count(*) 100。where过滤行having过滤分组这是组合使用时的关键区分。七、进阶五按布尔条件计数统计分组内的满足数除了统计每一组有多少行还常常需要统计每一组内有多少行满足某个条件。仓库文档 postgres/count-the-number-of-trues-in-an-aggregate-query.md 给出了用case表达式配合sum的经典写法select author_id, sum(case when available then 1 else 0 end) from books group by author_id;case在聚合前把布尔值转换为 1/0sum累加后即为可用书籍数。统计不满足条件的数量时只需反转分支sum(case when available then 0 else 1 end)这种按类型计数的变体在权限统计、状态分布、指标卡占比等场景中极为实用可以与group by自由组合成多维度的统计查询。八、小结按类型统计的查询范式综合原文档 postgres/count-records-by-type.md 及其在仓库中的系列姊妹篇可以归纳出按类型统计记录数的完整范式需求SQL 写法关键点每种类型各多少条select type, count(*) from t group by type;非聚合列必须在group by中按计数从多到少排序追加order by 2 desc或order by count(*) desc可用位置索引引用select参数NULL 类型也统计无需额外处理NULL 自动成为独立分组按派生特征统计group by substring(...)、group by date_trunc(...)表达式须在select与group by中一致只看满足条件的分组追加having count(*) N聚合结果过滤必须用having统计组内满足条件的行sum(case when ... then 1 else 0 end)case转 0/1 后聚合掌握这一组写法后任何带类型、状态、分类列的 PostgreSQL 表都可以用几条简洁的 SQL 完成分布统计——这也是数据分析与报表开发中使用频率最高的基础能力之一。相关完整示例与进阶变体可继续在仓库 postgres/ 目录下查阅 count-how-many-records-there-are-of-each-type.md、use-argument-indexes.md 与 group-by-the-result-of-a-function-call.md 等文档。赞分享文档教程知识库【免费下载链接】til:memo: Today I Learned项目地址https://gitcode.com/gh_mirrors/ti/til点击查看免费下载相关推荐Offer Formats by Business Type按业务类型选对报价结构的实战指南marketingskills 开源仓库解析Offer Formats by Business Type按业务类型选对报价结构的实战指南marketingskills 开源仓库解析 导读 同样的六个AI 技能人工智能最实用的LitePal聚合查询指南从GROUP BY到复杂统计分析最实用的LitePal聚合查询指南从GROUP BY到复杂统计分析 你是否还在为Android项目中的数据统计功能编写大量SQL语句是否遇到过需要按类别统计数据库ORM移动开发Open-Meteo零密钥的免费天气 API一条 curl 拿全球预报Open Meteo零密钥的免费天气 API一条 curl 拿全球预报 Open Meteo 是一个用 Swift 编写的开源气象数据服务它把 NOAA后端API网关数据工程上一篇老游戏兼容工具 DDrawCompat3 步让《星际争霸》《暗黑2》在 Win10/11 上满血复活下一篇老游戏画面模糊还闪退DDrawCompat兼容工具从零上手完全指南创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考