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。

相关推荐
CHANG_THE_WORLD8 小时前
switch case 二分搜索风格
前端·数据库
DarkAthena8 小时前
【ORACLE】分区表数据倾斜会发生什么
数据库·oracle
indexsunny9 小时前
互联网大厂Java求职面试实战:微服务与Spring Boot在电商场景中的应用
java·数据库·spring boot·微服务·kafka·hibernate·电商
DarkAthena9 小时前
【GaussDB】数据静止状态下同一个SQL或同一个存储过程执行第6次报错的问题排查
数据库·sql·gaussdb
huwei8539 小时前
QT 连接数据库类
数据库·qt·oracle
l1t9 小时前
郭其先生利用DeepSeek实现的PostgreSQL递归CTE实现DFS写法
sql·算法·postgresql·深度优先
尽兴-9 小时前
MySQL 中一条 SQL 的执行流程详解
sql·mysql·adb·dba
wangbing11259 小时前
平台介绍-开放API后台微服务
数据库·微服务·架构
高一要励志成为佬9 小时前
【数据库】第三章 关系数据库标准语言SQL
数据库·sql