数据分类汇总的四种方法

四种方法:透视表、SQL查询、pandas库、专用软件。

1 . 透视表:Excel功能。
拖拽字段。
1 0秒出结果。
按产品求和销售额。

2 . SQL查询:数据库语言。
GROUP BY子句。
5 分钟写查询。
按产品求和销售额。

3 . pandas库:Python库。
groupby函数。
3 0行代码。
按产品求和销售额。

4 . 专用软件:SPSS/SAS。
菜单操作。
1 小时上手。
大规模分析。

选择工具看数据量。
1 0万行内透视表最快。
百万行以上用SQL或pandas。
千万行以上上专用软件。

提醒:小数据用Excel,大数据用代码。

SQL 分组查询如何优化 COUNT 统计?

哎哟,别整那么复杂,听我给你唠唠我踩过的坑。

前年,我在北京搞一个电商项目,数据量不大,也就几百w。
那会儿写个统计订单数的SQL,直接用 COUNT() 就挺快的,因为订单表有个自增ID做主键,数据库自动索引了,查起来那叫一个溜。

后来,数据慢慢上来了,到千万级别了。
有回需求要统计每个用户的订单数量,写了个 SELECT user_id, COUNT() FROM orders GROUP BY user_id。
结果你猜怎么着?直接卡死,查半天没结果。
后台一看,CPU飙到9 0%,磁盘I/O也挂了。
我一琢磨,问题来了。

索引优化这事儿,真不能瞎来。

我赶紧加了个复合索引 CREATE INDEX idx_user_id ON orders(user_id)。
这下子,再跑那个查询,嗖一下就出结果了。
为啥?因为数据库可以直接用索引里的 user_id 那列去分组,不用去一条条订单数据看了。
这就是索引顺序设计的重要性。
你要是搞个 CREATE INDEX idx_id_user ON orders(id, user_id),那分组效率就差远了,因为 user_id 不是索引的第一列。

还有覆盖索引,也是我踩坑的地方。
有一次,需求要查某个城市的用户订单数 SELECT city, COUNT() FROM orders WHERE city = '北京' GROUP BY city。
我一开始也是用 COUNT(),结果发现慢。
后来我一看,订单表里 city 这列没啥索引。
我就建了个覆盖索引 CREATE INDEX idx_city ON orders(city)。
这下好了,查询直接用索引里的 city 就统计完了,根本不用回表查其他数据。
这就是覆盖索引的威力。

但是,索引也不是越多越好。

我之前有个项目,数据量也就几w,结果我建了十几个索引。
每次新增订单,写操作就慢得要死。
你想想,每次插入数据,数据库不光要写数据本身,还得更新所有相关的索引。
那会儿我真是头大,最后只能一个个删掉不必要的索引,写操作才恢复到正常速度。
所以啊,索引设计要结合查询频率和数据更新频率,别瞎建。

COUNT() 和 COUNT(列名),这俩也是有区别的。

一般我都用 COUNT(),因为它统计行数,不管列值是不是NULL,效率最高。
比如 SELECT COUNT() FROM orders WHERE status = '已发货',数据库可以直接利用 status 列的索引(如果有的话)来统计行数。

但有回,我写了个 SELECT COUNT(status) FROM orders WHERE status = '已发货',结果发现效率特别低。
后来一查,原来 COUNT(status) 要去检查每一行的 status 列是不是NULL,如果 status 列没索引,或者有很多NULL值,那数据库可能就没办法利用索引,只能全表扫描。
所以啊,统计行数用 COUNT(),统计非NULL值的数量,要确保那列有索引。

数据量一大,查询优化就特别重要。

有一次,我遇到一个TB级别的数据,要统计每天每个用户的订单数。
直接跑 SELECT date, user_id, COUNT() FROM orders GROUP BY date, user_id,那数据库直接就挂了。
后来我学聪明了,先跑个子查询,把日期过滤一下,比如 WITH jan_data AS (SELECT FROM orders WHERE date BETWEEN '2 02 4 -01 -01 ' AND '2 02 4 -01 -3 1 ') SELECT date, user_id, COUNT() FROM jan_data GROUP BY date, user_id。
这样参与分组的数据量就小多了,查询速度就快了。

还有,数据分区这招我也用过。
比如按月分区,查询某个月的数据,数据库就只扫描那个分区的数据,不用扫描全表。
我之前建表的时候,就按日期分区了 CREATE TABLE orders PARTITION BY RANGE (date) (PARTITION p2 02 4 01 VALUES LESS THAN ('2 02 4 -02 -01 '), ...)。
结果有回跑年度报表,直接只扫描了对应年份的分区的数据,性能提升不是一点半点。

最后,TB级别的数据,光靠数据库优化可能不够。

有回,我搞一个实时报表,数据更新很快。
直接用数据库统计,肯定跟不上。
后来我就用了物化视图,定期从数据库里把需要的数据聚合一下,存到一个单独的表里。
这样查报表的时候,直接查那个物化视图的表,速度飞快。
当然,这也是要牺牲一点数据实时性的。

总之啊,SQL优化是个技术活,得结合实际情况。
索引设计、COUNT() 还是 COUNT(列名)、查询重构,这些都得根据你的数据量、查询需求来调整。
别想着一招鲜吃遍天,实际情况千变万化,得灵活应对。

SQL 分组查询如何按月份统计?

记得有一次,我在一个周末的下午,坐在电脑前,面对着满满一屏的SQL语句,试图从成千上万条销售记录中提取出每个月的销售额。
那时候,我还在学习如何使用SQL进行日期的分组统计,那时候的我是多么的迷茫啊。
我尝试了MySQL的DATE_FORMAT函数,但是发现数据格式不对,于是我又去查了PostgreSQL的TO_CHAR函数,结果还是不行。
我坐在那里,一边敲击键盘,一边心里默默念叨:“等等,我还有个事,SQLServer的FORMAT函数好像也可以做到这个。

我试着把FORMAT函数应用到SQL语句中,结果屏幕上立刻出现了我想要的“年-月”格式的数据。
那一刻,我心中的石头终于落地了。
我统计出了每个月的销售额,从1 月到1 2 月,每个月的销售额都清晰可见。
我记得当时我统计出的最高销售额是2 02 3 年7 月的,达到了1 0万元。

但是,我也突然想到,如果我要统计的是所有年份中每个月的销售额总和,那该怎么办呢?我查了一下,原来可以通过MONTH函数来实现,这样就可以把所有年份的同一月份的数据合并在一起了。
这让我对SQL的日期函数有了更深的理解。

那天晚上,我回家后,还在回味着这个小小的成就。
是的,虽然只是一个小小的统计,但它让我对SQL有了更深的认识,也让我明白了,无论是学习还是工作,都需要一点一滴的积累。