SQL核心(1)

1:注意点

1.1:描述:

用户表用8人,但是订单表只有7个人的订单,在统计每个用户的订单数量的时候,要注意count(*),count(列名),null值的处理

1.2:原有SQL:

sql 复制代码
select a.user_id,count(*) from dim_users a left join fact_orders b 
on a.user_id = b.user_id 
group by a.user_id

1.3:发现问题(结果)

结果是,一个用户没有订单时,根据下面的SQL,没有订单的用户 获取得到的订单总数 = 1;

1.4:分析和解决问题

1:问题描述

select a.user_id,count(*) from dim_users a left join fact_orders b on a.user_id = b.user_id group by a.user_id ; 为什么表dim_users有8个用户,表fact_orders只有7个用户的订单;但是最后没有订单的用户=1;
核心:count(*) 和count(列名)

COUNT(*) 统计的是行数(是否存在这行)。
COUNT(列名) 统计的是该列中非 NULL 值的个数。

1.2:分析:

关键点在于,由于是 LEFT JOIN主表 dim_users 的所有记录都会被保留 。对于没有匹配订单的用户U8,来自 fact_orders 表的所有字段都会用 NULL 填充。

接下来,GROUP BY a.user_id 对这个结果集进行分组,然后 COUNT(*) 统计每个分组内的行数

  • 对于用户 U1 到 U7:他们的分组里都至少有一条与订单匹配的记录,COUNT(*) 的结果就是他们的订单数量(可能是1,也可能是多条)。

  • 对于用户 U8:他的分组里只有 1 行 (就是那条由 LEFT JOIN 生成的、订单字段全为 NULL 的行)。因此,COUNT(*) 的结果是 1

1.3:结论和建议

✅ 结论与建议

所以,你的查询结果准确地显示了:8个用户都出现在结果中,其中7个有订单的用户显示了订单数,那1个没有订单的用户计数为1。

如果你想更直观地看到"没有订单的用户数为0",可以将 COUNT(*) 改为 COUNT(b.user_id)COUNT(b.order_id)。这是因为 COUNT(列名) 会忽略该列的 NULL

SELECT

a.user_id,

COUNT(*) AS total_rows, -- 会为无订单用户返回1

COUNT(b.user_id) AS order_count -- 会为无订单用户返回0

FROM dim_users a

LEFT JOIN fact_orders b ON a.user_id = b.user_id

GROUP BY a.user_id;

运行上面的修改后查询,你就能清楚地看到 COUNT(*)COUNT(特定列) 在处理 NULL 值时的核心区别了。

如果你还有其他关于 SQL 逻辑的疑问,随时可以提出。

1.5:区分count(*)和count(列名)

  1. COUNT(*) 是"元组计数"

    • 它关心的是"行"这个容器本身 。只要这行数据存在,无论其内部字段是值还是 NULL,它都客观占据一行。因此,它必然包含所有行。

    • 在上面的 LEFT JOIN 例子中,即使用户U8对应的订单字段全是 NULL,但这一行数据是确定存在的 ,所以 COUNT(*) 会将其计入。

  2. COUNT(列名) 是"值计数"

    • 它关心的是某个特定"值"是否有效 。在 SQL 中,NULL 表示"未知"、"缺失"或"不适用",不是一个有效的"值"。因此,在统计时,所有 NULL 都会被排除在外。

    • LEFT JOIN 的例子中,对 COUNT(b.user_id) 来说,用户U8对应的 b.user_idNULL,所以被忽略,结果为0。

相关推荐
Maverick061 小时前
Oracle Redo 日志操作手册
数据库·oracle
攒了一袋星辰1 小时前
高并发强一致性顺序号生成系统 -- SequenceGenerator
java·数据库·mysql
W.D.小糊涂2 小时前
gpu服务器安装windows+ubuntu24.04双系统
c语言·开发语言·数据库
云贝教育-郑老师2 小时前
【OceanBase 的多租户架构是怎样的?有什么优势?】
数据库·oceanbase
顶点多余2 小时前
使用C/C++语言链接Mysql详解
数据库·c++·mysql
xiaokangzhe2 小时前
MySQL 数据库操作
数据库·oracle
发际线还在4 小时前
互联网大厂Java三轮面试全流程实战问答与解析
java·数据库·分布式·面试·并发·系统设计·大厂
小王不爱笑1324 小时前
MyBatis 执行流程源码级深度解析:从 Mapper 接口到 SQL 执行的全链路逻辑
数据库·sql·mybatis
山峰哥5 小时前
SQL优化实战:从索引策略到执行计划的极致突破
数据库·sql·性能优化·编辑器·深度优先
总要冲动一次5 小时前
离线安装 percona-xtrabackup-24
linux·数据库·mysql·centos