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

非聚合列指的是未被聚合函数(如SUMAVGMAXCOUNT等)处理的列

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}


相关文章
|
4月前
|
消息中间件 存储 缓存
再次了解kafka
Kafka通过offset机制解决消息重复消费问题,支持手动提交偏移量及唯一ID去重。它保证分区内的消息顺序消费,结合集群、副本与重平衡实现高可用。高性能设计包括顺序读写、分区、页缓存、零拷贝等。数据清理依赖保留时间或大小策略,点对点和发布订阅模式则通过消费者组实现。
|
4月前
|
消息中间件 NoSQL Java
延时实现
本节介绍了多种关闭过期订单的实现方案,包括定时任务、JDK延迟队列、Redis过期监听、Redisson延迟队列、RocketMQ延迟消息及RabbitMQ死信队列。各自优缺点明显,适用于不同业务场景,如定时任务适合小数据量,RocketMQ适合高并发解耦场景,而Redisson则使用简单且高效。选择时需综合考虑系统复杂度、数据量及可靠性要求。
|
4月前
|
存储 缓存 Linux
CPU上下文切换的原理及其在系统调用和进程切换中的应用
本内容深入解析了CPU上下文切换的原理及其在系统调用和进程切换中的应用。详细说明了CPU寄存器、程序计数器在任务切换中的作用,以及系统调用与进程上下文切换的区别。同时探讨了上下文切换带来的性能开销,涉及TLB和虚拟内存管理机制,帮助理解操作系统如何高效调度进程。
|
4月前
|
负载均衡 网络性能优化
了解EMQ
EMQ通过MQTT协议的QoS机制保障消息可靠传输,支持QoS 0、1、2三个等级,分别实现消息最多一次、至少一次和恰好一次传递。对于延迟消息,EMQ X支持通过特殊主题前缀`$delayed/{DelayInterval}`实现延迟发布。点对点通信可通过不带群组的共享订阅(如`$queue/t/1`)实现,结合负载均衡策略如随机、轮询等,确保消息仅由一个订阅者接收;发布订阅模式则通过带群组的共享订阅(如`$share/组名称/t/1`)实现,确保每组一个订阅者收取消息。
|
4月前
|
存储 算法 Sentinel
熔断降级
本内容介绍了微服务中熔断降级的实现原理及Sentinel的底层机制。通过OpenFeign集成Sentinel,利用断路器统计异常和慢请求比例,触发熔断并降级,提升系统稳定性。还讲解了Sentinel使用的限流算法,如滑动窗口、令牌桶和漏桶算法,以应对不同场景下的流量控制需求。
|
4月前
|
Docker 容器
初始ollama
Ollama 按需加载模型,不持续运行,闲置时自动卸载,节省内存。模型响应请求时驻留内存,保留时间由 OLLAMA_KEEP_ALIVE 控制。类似 Docker 部署方式,但无单模型启停命令,默认时间内自动停止。可间接通过停止服务或配置多端口实现管理。
|
4月前
|
XML JSON Java
Spring框架中常见注解的使用规则与最佳实践
本文介绍了Spring框架中常见注解的使用规则与最佳实践,重点对比了URL参数与表单参数的区别,并详细说明了@RequestParam、@PathVariable、@RequestBody等注解的应用场景。同时通过表格和案例分析,帮助开发者正确选择参数绑定方式,避免常见误区,提升代码的可读性与安全性。
|
4月前
|
SQL Java 数据库连接
事务的七种传播行为及其应用场景
本文介绍了事务的七种传播行为及其应用场景,包括 PROPAGATION_REQUIRED、PROPAGATION_SUPPORTS、PROPAGATION_REQUIRES_NEW 等,帮助开发者理解事务管理机制。同时讲解了 Java 中 SQL 操作与对象数据不同步的问题,强调重新查询与手动管理的必要性,并说明 MyBatis 批量操作的最佳实践。
|
4月前
|
SQL JavaScript Java
三层架构理解(实现前后端分离)
本文介绍了三层架构实现前后端分离的流程,从前端Vue发起请求,到后端Spring处理数据,最后返回结果并由前端渲染展示。同时详细解析了Bean重复问题的解决方案,包括使用@Service、@Primary、@Qualifier和@Resource注解进行依赖注入控制。此外还介绍了MyBatis中#{}与${}的区别及使用场景,以及三层架构中各组件的协作方式。