sql了解3

简介: 本文介绍了SQL中分组查询(GROUP BY)的规则,强调SELECT中的列必须是GROUP BY中的列或被聚合函数包裹的列。同时解释了非聚合列的定义及其在GROUP BY中的必要性,并通过代码示例展示了简单CASE WHEN和搜索CASE WHEN的用法,最后对比了两种模式的区别。

分组查询规则:(group by)
SELECT 中的列必须满足以下其一:

  1. 出现在 GROUP BY 中(如 deptno)。
  2. 被聚合函数包裹(如 MAX(sal))

,SELECT 中的非聚合列必须全部出现在 GROUP BY 中

非聚合列指的是未被聚合函数(如SUM、AVG、MAX、COUNT等)处理的列。

SELECT ename, sal 
FROM emp 
GROUP BY ename, sal;  -- 同时按ename和sal分组
-- 结果等价于不分组(假设ename唯一),分组就没作用,等价于输出select ename, sal 
FROM emp


SELECT 
    dept_id,           -- GROUP BY中的列
    AVG(salary)        -- 聚合函数(不在GROUP BY中)
FROM employees
GROUP BY dept_id;

case when then 两种模式

简单模式

SELECT 
    CASE dept_id
        WHEN 1 THEN '技术部'
        WHEN 2 THEN '市场部'
        WHEN 3 THEN '销售部'
        ELSE '未知部门'
    END AS dept_name
FROM employees;

核心:先计算 expression 的值,再将其与每个 WHEN 后的 value 进行等值比较。

搜索模式

sql

SELECT 
    emp_name,
    salary,
    CASE
        WHEN salary > 3000 THEN '高级'
        WHEN salary > 2000 AND salary <= 3000 THEN '中级'
        WHEN salary <= 2000 THEN '初级'
        ELSE '未知'
    END AS level
FROM employees;
  • 核心:直接在 WHEN 后写条件表达式,按顺序判断每个条件的真假。

对比项

简单模式

搜索模式

表达式位置

CASE

后必须有一个表达式(如列名)

CASE

后无表达式,直接写 WHEN

条件类型

WHEN

后只能是值(用于等值比较)

WHEN

后是条件表达式(如 sal > 3000

)

比较逻辑

固定为 expression = value

支持任意条件(如 >

, <

, LIKE

, AND

等)

示例

CASE dept_id WHEN 1 THEN '技术部'

CASE WHEN dept_id = 1 THEN '技术部'

简单模式,只能等值比较,搜索模式可以进行判断;简单模式 case后要加列名,搜索模式则是直接case 后面接when

if写法(case-when-then可以完全替代)

SELECT 
    score,
    IF(score >= 60, '及格', '不及格') AS status
FROM exams;

聚合函数 只能放在select之后(放列名的地方)或者having之后,而having必须与groupby一起使用(having是对分组之后的结果进行筛选)

MySQL 的 ONLY_FULL_GROUP_BY 模式 下,是的 —— 只要 SELECT 中包含 聚合函数 和 非聚合列,则 非聚合列必须全部包含在 GROUP BY 子句中(某列通过 函数依赖 与 GROUP BY 中的列关联,则可省略。)。

循环递归(属性结构)

/**
     * 菜单名称
     */
@Data
@ApiModel("树形结构VO")
public class TreeVo {
    // 字段定义
     @ApiModelProperty(value = "菜单名称")
    private String label;
    /**
     * 菜单ID
     */
    @ApiModelProperty(value = "菜单ID")
    private String value;
    /**
     * 子菜单
     */
    @ApiModelProperty(value = "子菜单")
    private List<TreeVo> children;
}
   循环调用,类似树形结构
[
  {
    "label": "一级菜单A",
    "value": "1",
    "children": [
      {
        "label": "二级菜单A-1",
        "value": "1-1",
        "children": [] // 空列表表示叶子节点
      },
      {
        "label": "二级菜单A-2",
        "value": "1-2",
        "children": [
          {
            "label": "三级菜单A-2-1",
            "value": "1-2-1",
            "children": []
          }
        ]
      }
    ]
  },
  {
    "label": "一级菜单B",
    "value": "2",
    "children": []
  }
]

<resultMap id="TreeVoResultMap(别名随意)" type="com.zzyl.nursing.vo.TreeVo">
   **************   外层:楼层*************
    // column 对应的字段名(数据库中的字段,要与下面的sql对应)
    //property 对应的实体类属性名
    <id column="fid" property="value"></id>  
    <result column="name" property="label"></result>
    ***************中层:房间********************************
    <collection property="children" ofType="com.zzyl.nursing.vo.TreeVo">
        <id column="rid" property="value"></id>
        <result column="code" property="label"></result>
        ************ 内层:床号***************
        <collection property="children" ofType="com.zzyl.nursing.vo.TreeVo">
            <id column="bid" property="value"></id>
            <result column="bed_number" property="label"></result>
        </collection>
    </collection>
</resultMap>
<select id="getRoomAndBedByBedStatus" resultMap="TreeVoResultMap">
    select f.id fid, f.name, r.id rid, r.code, b.id bid, b.bed_number
    from floor f
             left join room r on f.id = r.floor_id
             left join bed b on r.id = b.room_id
    where b.bed_status = #{status}
    order by f.id, r.id, b.id
</select>

片段引用(实现sql的复用)

<!-- 定义可复用的 SQL 片段 -->
<sql id="selectNursingLevelVo">
    SELECT 
        id, 
        level_name, 
        level_code, 
        description,
        create_time,
        update_time
    FROM nursing_level
</sql>
<!-- 使用该片段的查询 -->
<select id="selectNursingLevelById" parameterType="Long" resultMap="NursingLevelResult">
    <include refid="selectNursingLevelVo"/>
    WHERE id = #{id}
</select>
实际执行:
SELECT 
    id, 
    level_name, 
    level_code, 
    description,
    create_time,
    update_time
FROM nursing_level
WHERE id = #{id}


相关文章
|
Java 测试技术 数据库连接
【MyBatisPlus】MyBatisPlus 整合开发
【1月更文挑战第19天】【MyBatisPlus】MyBatisPlus 整合开发
|
6月前
|
JSON 前端开发 Java
【注解】@RequestBody与@ResponseBody 全方位对比全解
本文全方位解析Spring中`@RequestBody`与`@ResponseBody`:从`HttpMessageConverter`底层机制、数据流向(入站反序列化 vs 出站序列化)、使用限制、组合实践(`@RestController`)、配置技巧到高频踩坑,助你深入掌握RESTful接口开发核心。
|
机器学习/深度学习 人工智能 算法
ProtGPS:MIT再造生命科学新基建!蛋白质AI一键预测定位+设计新序列,登Nature子刊
ProtGPS 是麻省理工学院和怀特黑德研究所联合开发的蛋白质语言模型,能够预测蛋白质在细胞内的亚细胞定位,并设计具有特定亚细胞定位的新型蛋白质。
1291 17
ProtGPS:MIT再造生命科学新基建!蛋白质AI一键预测定位+设计新序列,登Nature子刊
|
安全 图形学
Unity射线检测的“坑”
在 Unity 中,射线检测是常用功能,但也存在一些常见问题。首先是层(Layer)设置问题,如射线忽略某些层或误检测到不期望的层,需正确设置 LayerMask。其次是碰撞体相关问题,包括碰撞体未启用或类型不匹配,确保碰撞体启用并合理设置属性。再者是射线起始点和方向问题,错误的位置或方向计算会导致检测失败,需准确设置起始点和方向。此外,频繁进行射线检测或检测范围过大会影响性能,应减少检测次数并合理设置范围。最后,在多线程中进行射线检测可能导致错误,应避免在非主线程中直接调用射线检测。
|
XML Java C语言
yaml语法格式,springboot中yaml的使用
本文介绍了YAML的语法格式和数据类型表示方法,并详细讲解了如何在Spring Boot中使用YAML,包括@ConfigurationProperties注解及Bean的创建、编写Controller、配置application.yaml配置文件,以及在pom.xml中开启YAML提示。
|
SQL 存储 大数据
Hive的查询、数据加载和交换、聚合、排序、优化
Hive的查询、数据加载和交换、聚合、排序、优化
984 2
|
Java 开发工具 数据库
从mybatis-plus-generator看如何编写代码生成器
velocity模板引擎分三步,1.初始化 配置模板加载地址;2.放置上下文变量velocityContext;3.渲染模板。
1132 0
从mybatis-plus-generator看如何编写代码生成器
|
JSON 前端开发 Java
一文读Web开发 之接口后端接口、类与前端请求、拦截器编写
一文读Web开发 之接口后端接口、类与前端请求、拦截器编写
2157 6
|
存储 缓存 算法
详解JVM内存优化技术:压缩指针
详解JVM内存优化技术:压缩指针

热门文章

最新文章