当前位置: 首页 > news >正文

mysql学习day1

学习资料:
https://yrzu9y4st8.feishu.cn/sheets/FIussTNr2hyC5ktUJZicKh08nEh

配合b站戴师兄视频

我没听懂的地方1:

SELECT continent, gdp 人均gdp FROM world where (gdp>20000000000 and population>60000000) or (gdp<8000000000 and name like '%a%a%a%') group by continent having sum(population) > 300000000 order by count(name) desc limit 1为什么用sql这一段报错呢

你的这段 SQL 报错,核心原因是SELECT 子句中的列与 GROUP BY 分组逻辑不匹配

一、错误原因分析

  1. SELECT 列与 GROUP BY 不兼容SQL 的分组(GROUP BY)规则要求:SELECT 中出现的非聚合列(如gdp),必须出现在 GROUP BY 中;反之,GROUP BY 中的列(如continent)可以出现在 SELECT 中。你的代码中SELECT continent, gdp里,gdp是单行列(未聚合),但没出现在 GROUP BY 中,这是最核心的报错原因。

  2. 人均 GDP 计算逻辑错误gdp/sum(population)的写法不合理:gdp是单个国家的 GDP,而sum(population)是整个大洲的总人口,用单个国家的 GDP 除以大洲总人口,不符合 “人均 GDP” 的计算逻辑(正确逻辑是:大洲总 GDP / 大洲总人口)。

  3. 条件执行顺序问题WHERE 子句在 GROUP BY 之前执行,会先过滤行,再分组;你的需求是 “先筛选符合条件的国家,再按大洲分组”,这个逻辑本身没问题,但需要确保分组后的聚合计算正确。

二、修正后的代码

先明确需求:筛选出符合条件的国家(GDP>200 亿且人口 > 6000 万,或 GDP<80 亿且名称含至少 3 个 a),按大洲分组,筛选出总人口> 3 亿的大洲,计算该大洲的人均 GDP(总 GDP / 总人口),最后按国家数量降序取第一个大洲。

SELECT continent, SUM(gdp)/SUM(population) AS 人均gdp, -- 修正:用大洲总GDP除以大洲总人口 COUNT(name) AS 国家数量 -- 便于理解排序逻辑 FROM world WHERE (gdp > 20000000000 AND population > 60000000) OR (gdp < 8000000000 AND name LIKE '%a%a%a%') GROUP BY continent -- 仅按大洲分组,SELECT中只能用聚合列或continent HAVING SUM(population) > 300000000 ORDER BY COUNT(name) DESC LIMIT 1;

三、关键修改说明

  1. 人均 GDP 计算修正:将gdp/sum(population)改为SUM(gdp)/SUM(population),确保用大洲总 GDP除以大洲总人口,符合人均 GDP 的定义。
  2. SELECT 列合规化:SELECT 中仅保留continent(GROUP BY 列)和聚合函数(SUM/COUNT),避免非聚合列导致的语法错误。
  3. 新增辅助列:添加COUNT(name) AS 国家数量,便于你直观看到排序依据(可根据需要删除)。

改成sum(gdp)的语义我理解 但是为什么这样就不报错了呢,聚合函数就可以了吗

你这个问题问到了 SQL 分组查询的核心规则,我用通俗的方式给你讲清楚:为什么用聚合函数SUM(gdp)就不报错,而直接用gdp会报错。

一、先理解:GROUP BY 分组后,SQL “看不到” 单个行的数据了

你可以把GROUP BY continent想象成:

  • 原始表是 “按国家一行行排列” 的(比如中国、美国、日本各占一行,各有自己的 gdp、population);
  • 执行GROUP BY continent后,SQL 会把同一个大洲的所有国家行 “打包合并” 成一行(比如亚洲所有国家合并成 “亚洲行”,欧洲所有国家合并成 “欧洲行”)。

此时:

  • 如果你直接写gdp,SQL 会懵:“你要哪个 gdp?亚洲有中国的 gdp、印度的 gdp、日本的 gdp… 我该选哪个?” → 所以直接报 “非聚合列未分组” 的错;
  • 如果你写SUM(gdp),SQL 就明确了:“哦,你要的是这个大洲所有国家 gdp 加起来的总和” → 这是一个确定的、唯一的值,所以不会报错。

二、核心规则:GROUP BY 的 “列合法性” 要求

SQL 标准(尤其是 MySQL 5.7+、PostgreSQL、Oracle 等主流数据库)强制要求:

SELECT 子句中出现的列,必须满足二选一

  1. GROUP BY子句中明确指定的分组列(比如你的continent);
  2. 被聚合函数(SUM/COUNT/AVG/MAX/MIN 等)包裹(比如SUM(gdp)SUM(population))。
举个直观的例子对比
写法SQL 的理解是否报错
SELECT gdp要单个国家的 gdp,但分组后是 “大洲行”❌ 报错
SELECT SUM(gdp)要大洲所有国家 gdp 的总和✅ 不报错
SELECT continent分组列本身,每个大洲只有一个值✅ 不报错

三、聚合函数的本质:把 “一组值” 变成 “一个值”

聚合函数(SUM/COUNT/AVG 等)的核心作用,就是对 “打包合并” 后的一组数据做计算,最终输出一个唯一值,刚好匹配 GROUP BY 后 “每个分组只有一行” 的特性:

  • SUM(gdp):把一个大洲所有国家的 gdp 加起来 → 每个大洲只有一个 “总 gdp”;
  • COUNT(name):统计一个大洲符合条件的国家数量 → 每个大洲只有一个 “国家数”;
  • AVG(population):计算一个大洲所有国家的人口平均值 → 每个大洲只有一个 “平均人口”。

而未被聚合的gdp是 “一组值”(一个大洲有多个国家就有多个 gdp),SQL 无法确定该取哪一个,因此严格遵循标准的数据库都会报错(早期 MySQL 宽松模式下可能不报错,但会随机取一个值,结果不可靠)。

我没听懂的地方2:

你看一下这个题目 我很奇怪 为什么'%'不代表%这个符号本身呢 就像字母string一样 而且concat函数之后出来的是什么数据 是string吗

一、先回答你的两个核心疑问

1. 为什么%不代表符号本身,而是通配符?

在 SQL 的LIKE运算符里,%特殊通配符,不是普通字符:

  • %代表「任意长度(包括 0 个)的任意字符」
  • 如果你想让%变成普通符号本身,需要用转义符,比如LIKE 'a\%b' ESCAPE '\'才会匹配a%b这样的字符串
  • 题目里的concat('%', name, '%')是故意用%做通配符,目的是匹配「首都名称里包含国家名称」的情况
2.concat()函数返回什么数据类型?

concat()是字符串拼接函数,输入是字符串 / 可转成字符串的类型,输出一定是字符串(string)。比如:

concat('%', 'Mexico', '%') → 结果是字符串 `%Mexico%`

这个结果会直接传给LIKE作为匹配模式。


二、结合题目拆解整段逻辑

题目要求:首都是国家名称的扩展→ 满足两个条件:

  1. 首都名称里包含国家名称(比如Mexico City包含Mexico
  2. 首都名称 ≠ 国家名称(排除卢森堡这种capital = name的情况)

参考代码的逻辑:

where capital like concat('%', name, '%') -- 首都里包含国家名 and capital != name; -- 首都名和国家名不相同
  • concat('%', name, '%')生成%国家名%这样的匹配模式
  • capital like '%国家名%'就会匹配「首都名称中包含国家名」的所有行
  • 再用capital != name排除掉「首都名 = 国家名」的特例(比如卢森堡)

三、举个具体例子帮你理解

namecapitalconcat('%', name, '%')like 匹配结果capital != name是否被选中
MexicoMexico City%Mexico%✅ 匹配✅ 不等✅ 选中
LuxembourgLuxembourg%Luxembourg%✅ 匹配❌ 相等❌ 排除
FranceParis%France%❌ 不匹配-❌ 排除

四、补充:如果想让%变成普通符号该怎么做?

如果你的需求是匹配「首都里真的包含%这个符号」,就需要转义:

-- 匹配 capital 里包含字符 % 的行 where capital like '%\%%' ESCAPE '\';

这里\是转义符,\%就代表%符号本身,不再是通配符。

所以我capital不需要写成 'capital' like concat('%', name, '%')

你完全说对了!绝对不需要capital写成'capital'(加单引号),这是新手很容易混淆的一个点,我帮你把这个关键区别讲透:

核心区别:单引号 vs 无引号

写法含义能否正确运行
capital数据库表中的字段名(比如存储首都名称的列)✅ 正确
'capital'一个固定的字符串字面量(就是字符 c-a-p-i-t-a-l 组成的文本)❌ 错误

举个直观的例子

假设表中有这样一行数据:

namecapital
ChinaBeijing
  1. 正确写法:capital LIKE concat('%', name, '%')

    • 实际执行的是:'Beijing' LIKE '%China%'→ 判断「Beijing 字符串是否包含 China」,结果是false(符合逻辑)。
  2. 错误写法:'capital' LIKE concat('%', name, '%')

    • 实际执行的是:'capital' LIKE '%China%'→ 判断「capital 字符串是否包含 China」,结果永远是false(因为 capital 里根本没有 China),完全偏离了你的需求。

补充:什么时候需要单引号?

只有当你想表示固定的文本 / 字符串值时,才需要加单引号:

  • 匹配固定字符串:capital = 'Beijing'(判断字段值是否等于固定字符串 Beijing);
  • 拼接固定字符:concat('【', capital, '】')(给首都名加【】,比如变成「【Beijing】」)。

而字段名(比如 capital、name、gdp、population)是数据库里定义的列名,永远不需要加单引号,加了就会被当成普通字符串,而非字段。

http://www.jsqmd.com/news/476669/

相关文章:

  • 跨平台集成:将OFA-VE嵌入Java企业应用
  • Android开发必备:如何优雅调用高德、百度地图App(附完整代码与避坑指南)
  • switch-case多分支选择结构
  • 实战演练:从华为ICT大赛真题看企业网络部署中的IPv6与安全认证陷阱
  • ESP8685硬件安全加速器与外设协同设计深度解析
  • 匿名无人机S.Bus模式设置全攻略:从遥控器到飞控的完整配置流程
  • Unity遮罩优化:用Shader替代Mask组件消除锯齿(附完整代码)
  • 物流优化必看:遗传算法在配送路径规划中的调参指南(以TSP为例)
  • 计算机网络:自顶向下方法(第七版)第三章 学习分享(三)
  • Windows 11下mmdet3d v0.17.1环境配置与常见错误解决指南
  • Nomic-Embed-Text-V2-MoE与网络原理:深入理解互联网传输协议对模型API延迟的影响
  • 【C++】spdlog基础使用
  • Mellanox网卡SR-IOV配置避坑指南:解决‘not enough MMIO resources‘报错(附完整参数解析)
  • 【2024】从Wumpus世界到智能体实战:基于PyGame与深度强化学习的探索与实现
  • Chrome DevTools字体太小?5分钟搞定自定义字体和样式(附完整CSS配置)
  • [Hello-CTF]RCE-Labs进阶解析:绕过preg_match的字符限制与通配符利用
  • 计算机毕业设计springboot校园食堂订餐系统 基于SpringBoot的高校智慧餐饮服务平台 SpringBoot驱动的校园线上餐饮预订与配送系统
  • 乐鑫ESP32/ESP8266射频测试全栈指南:从研发验证到量产落地
  • ESP32-S2-SOLO-2模组硬件架构与工程落地深度解析
  • ESP32-H2安全架构解析:寄存器控制、硬件加速与可信启动
  • 立创GD32VW553开发板模块移植手册:开源硬件生态构建指南
  • Win10家庭版升级专业版后,如何用Docker Desktop轻松玩转K8S(附避坑指南)
  • 从天空到算法:盘点那些定义无人机视觉研究的关键数据集
  • 迅为iMX6ULL开发板三大手册实战指南:从入门到精通
  • Zerotier vs Tailscale:哪个内网穿透工具更适合你的远程办公需求?
  • 解密navigator.geolocation.getCurrentPosition:从WGS84到GCJ02的坐标转换实战
  • 清音刻墨Qwen3在Vlog制作中的应用:一键生成高质量字幕
  • LongCat-Image-Editn V2生成效果一览:从换背景到加元素,样样精通
  • 在无外网环境下部署Prometheus与Grafana:构建企业级监控可视化平台
  • LiuJuan20260223Zimage场景实战:快速生成社交媒体配图与个人IP形象