复杂 SQL 实现分组分情况分页查询

其他系列文章导航

Java基础合集
数据结构与算法合集

设计模式合集

多线程合集

分布式合集

ES合集


文章目录

其他系列文章导航

文章目录

前言

[一、根据 camp_status 字段分为 6 种情况](#一、根据 camp_status 字段分为 6 种情况)

[1.1 SQL语句](#1.1 SQL语句)

[1.2 SQL解释](#1.2 SQL解释)

[二、分页 SQL 实现](#二、分页 SQL 实现)

[2.1 SQL语句](#2.1 SQL语句)

[2.2 根据 camp_type 区分返回字段](#2.2 根据 camp_type 区分返回字段)

[2.3 根据 camp_status 字段分为 6 种情况](#2.3 根据 camp_status 字段分为 6 种情况)

三、分页实现

四、总结


前言

在处理数据库查询时,分页是一个常见的需求。

尤其是在处理大量数据时,一次性返回所有结果可能会导致性能问题。

因此,我们需要使用分页查询来限制返回的结果数量。同时,根据特定的条件筛选数据也是非常常见的需求。

在本博客中,我们将探讨如何根据 camp_status 字段分为 6 种情况进行分页查询,并根据 camp_type 字段区分活动类型,返回不同的字段。

我们将使用 SQL 变量来实现这一功能,并通过示例进行详细解释。


一、根据 camp_status 字段分为 6 种情况

1.1 SQL语句

要将分页结果按 6 种情况来区分。

SQL如下:

sql 复制代码
SELECT         count(*)                                                                 AS allCampCount,
               SUM(CASE WHEN CAMP_STATUS IN ('31', '32', '35', '55') THEN 1 ELSE 0 END) AS approvalCampCount,
               SUM(CASE WHEN CAMP_STATUS IN ('40', '41', '56') THEN 1 ELSE 0 END)       AS toExecuteCampCount,
               SUM(CASE WHEN CAMP_STATUS IN ('42', '66', '67') THEN 1 ELSE 0 END)       AS executeCampCount,
               SUM(CASE WHEN CAMP_STATUS IN ('50', '60') THEN 1 ELSE 0 END)             AS completeCampCount,
               SUM(CASE WHEN CAMP_STATUS IN ('30') THEN 1 ELSE 0 END)                   AS overruleCampCount
        FROM BMA_MARKET_CAMP
        WHERE USER_ID = #{userId}

1.2 SQL解释

这是一个SQL查询,用于从名为BMA_MARKET_CAMP的表中选择和计算数据。下面是对这个查询的逐行解释:

  1. SELECT count(*) AS allCampCount: 这一行计算了BMA_MARKET_CAMP表中的总记录数,并将这个数量命名为allCampCount
  2. SUM(CASE WHEN CAMP_STATUS IN ('31', '32', '35', '55') THEN 1 ELSE 0 END) AS approvalCampCount: 这一行计算了CAMP_STATUS字段值为'31', '32', '35', 或 '55'的总数,并将这个数量命名为approvalCampCount。这些状态可能是表示"待批准"或"正在批准"的状态代码。
  3. SUM(CASE WHEN CAMP_STATUS IN ('40', '41', '56') THEN 1 ELSE 0 END) AS toExecuteCampCount: 这一行计算了CAMP_STATUS字段值为'40', '41', 或 '56'的总数,并将这个数量命名为toExecuteCampCount。这些状态可能是表示"待执行"或"即将执行"的状态代码。
  4. SUM(CASE WHEN CAMP_STATUS IN ('42', '66', '67') THEN 1 ELSE 0 END) AS executeCampCount: 这一行计算了CAMP_STATUS字段值为'42', '66', 或 '67'的总数,并将这个数量命名为executeCampCount。这些状态可能是表示"正在执行"或"已执行"的状态代码。
  5. SUM(CASE WHEN CAMP_STATUS IN ('50', '60') THEN 1 ELSE 0 END) AS completeCampCount: 这一行计算了CAMP_STATUS字段值为'50'或'60'的总数,并将这个数量命名为completeCampCount。这些状态可能是表示"已完成"或"完全完成"的状态代码。
  6. SUM(CASE WHEN CAMP_STATUS IN ('30') THEN 1 ELSE 0 END) AS overruleCampCount: 这一行计算了CAMP_STATUS字段值为'30'的总数,并将这个数量命名为overruleCampCount。这个状态可能是表示"已否决"或"推翻"的状态代码。
  7. FROM BMA_MARKET_CAMP WHERE USER_ID = #{userId}: 最后,指定了数据来源的表是BMA_MARKET_CAMP,并且只选择那些USER_ID字段等于给定参数#{userId}的记录。

总的来说,这个查询是为了获取与特定用户相关的各种 camp 状态的数量。


二、分页 SQL 实现

2.1 SQL语句

这是整个 SQL 语句,下面会细细讲解!

SQL如下:

sql 复制代码
        SELECT TOUCH_TYPE,
               t1.CAMP_TYPE,
               NAME,
               SMS_CONTENT,
               CASE
                   WHEN t1.CAMP_TYPE = '0' THEN
                       NULL
                   ELSE
                       START_DATE END AS START_DATE,
               CASE
                   WHEN t1.CAMP_TYPE = '0' THEN
                       EXE_START_TIME
                   ELSE
                       START_TIME END AS START_TIME,
               CASE
                   WHEN t1.CAMP_TYPE = '0' THEN
                       NULL
                   ELSE
                       END_DATE END   AS END_DATE,
               CASE
                   WHEN t1.CAMP_TYPE = '0' THEN
                       NULL
                   ELSE
                       END_TIME END   AS END_TIME
        FROM CAMP t1
                 left join CAMP_INFO t2 on t1.ID = t2.CAMP_ID
        WHERE CAMP_STATUS  in
        <foreach close=")" collection="campStatus" item="campStatus" open="(" separator=", ">
            #{campStatus,jdbcType=VARCHAR}
        </foreach>
          AND USER_ID = #{userId}

2.2 根据 camp_type 区分返回字段

  • 当活动类型为 0 时,只需要返回 EXE_STRAR_TIME 字段。
  • 其他的活动类型要返回 START_DATE , START_TIME , END_DATE , END_TIME 四个字段。

SQL部分如下:

sql 复制代码
               CASE
                   WHEN t1.CAMP_TYPE = '0' THEN
                       NULL
                   ELSE
                       START_DATE END AS START_DATE,
               CASE
                   WHEN t1.CAMP_TYPE = '0' THEN
                       EXE_START_TIME
                   ELSE
                       START_TIME END AS START_TIME,
               CASE
                   WHEN t1.CAMP_TYPE = '0' THEN
                       NULL
                   ELSE
                       END_DATE END   AS END_DATE,
               CASE
                   WHEN t1.CAMP_TYPE = '0' THEN
                       NULL
                   ELSE
                       END_TIME END   AS END_TIME

2.3 根据 camp_status 字段分为 6 种情况

解释如下:

  1. WHERE CAMP_STATUS in: 这表示我们要在SQL查询中添加一个条件,即CAMP_STATUS的值必须在给定的列表中。
  2. <foreach ...>: 这是MyBatis的循环语句,用于遍历集合或数组,并动态生成SQL的部分内容。
  3. collection="campStatus": 这表示我们要遍历的集合或数组的名称是campStatus
  4. item="campStatus": 在每次循环中,当前的元素值会被赋值给名为campStatus的变量。
  5. open="("close=")": 这些指示MyBatis在循环开始前添加一个左括号(,并在循环结束后添加一个右括号)
  6. separator=", ">: 这表示在每次循环后,我们添加一个逗号,`和一个空格。
  7. #{campStatus,jdbcType=VARCHAR}: 这是MyBatis的参数占位符。它表示我们要将当前循环中的campStatus变量的值插入到SQL查询中。jdbcType=VARCHAR指定了参数的类型,这里假设它是VARCHAR类型。

综上所述,这个片段的作用是动态生成一个SQL查询的条件,该条件检查CAMP_STATUS是否在给定的campStatus列表中。

SQL部分如下:

sql 复制代码
        SELECT 
            ...

        FROM 
            ...
        WHERE CAMP_STATUS  in
        <foreach close=")" collection="campStatus" item="campStatus" open="(" separator=", ">
            #{campStatus,jdbcType=VARCHAR}
        </foreach>
        ...

这里传入的是一个 list,这样传入即可:

定义一个请求类:

java 复制代码
@Data
public class CampDataInfoInIndexRequest {
    List<Integer> campStatusList;
    private int pageNum;
    private int pageSize;
}

三、分页实现

实现一个 PageUtils 。

代码如下:

java 复制代码
public class PageUtils {
    /**
     * 泛型方法 进行结果的分页
     * 当pageNum*pageSize>result.size那么就取result的最后一页数据
     * 否则就取相应页的数据
     *
     * @param result
     * @param pageNum
     * @param pageSize
     * @return
     */
    public static <T> List<T> pageResult(List<T> result, Integer pageNum, Integer pageSize) {
        if (Objects.isNull(result) || result.size() == 0) {
            return result;
        }
        int maxSize = result.size();
        if (maxSize < pageNum * pageSize + pageSize) {
            int maxPage = maxSize / pageSize;
            return result.subList(maxPage * pageSize, result.size());
        }
        return result.subList(pageNum * pageSize, (pageNum + 1) * pageSize);
    }
}

再通过一个 PageResultVO 返回即可。

代码如下:

java 复制代码
@Data
public class PageResultVO {
    private Integer total;
    private List<?> list;
}



//ServiceImpl层
List<CampInfoVO> infoList = PageUtils.pageResult(info, pageNum, pageSize);
PageResultVO pageResultVO = new PageResultVO();
pageResultVO.setTotal(info.size());
pageResultVO.setList(infoList);

四、总结

在这篇博客中,我们探讨了如何使用SQL实现分页查询,并根据camp_status和camp_type字段进行筛选。

通过使用变量和适当的SQL语法,我们可以根据特定的条件动态地构建查询,从而返回满足我们需求的结果。

通过这种方式,我们可以灵活地构建和执行查询,以满足不同的需求。这对于处理大量数据和实现复杂的筛选条件非常有用。

希望这篇博客能帮助你更好地理解和应用SQL分页查询和筛选功能!


相关推荐
南京码讯光电技术有限公司11 小时前
What Does Ex tb IIIC T80°C Db Mean?
服务器·网络·数据库
zephyr0511 小时前
链表实现O(n log n)时间复杂度的排序——归并排序详解
java·数据结构·算法
做萤石二次开发的哈哈12 小时前
萤石蓝海AIoT一站式工作台计费说明
网络·数据库·萤石开放平台·蓝海aiot一站式工作台
竹枝溪12 小时前
MySQL数据库零基础入门
数据库·sql·mysql·navicat·ddl·dml·dql
XWalnut12 小时前
LeetCode刷题 day37
java·数据结构·算法·leetcode
龙仔72512 小时前
人大金仓Kingbase V8 自动全量备份部署完整笔记
数据库·笔记·备份·人大金仓
王志来1379447300812 小时前
从选型到交付,工控服务器机箱一站式采购平台匀天如何实现服务闭环?
数据库
ShuiShenHuoLe12 小时前
HmarkX(码笺)的本地数据库模块重构实战
数据库·oracle·重构
Databend12 小时前
从 Kafka 到 Databend Cloud:万亿级 Agent Trace 接入链路的工程实践
大数据·数据库·agent
倔强的石头_12 小时前
SQL Server数据迁移,不只是把数据搬过去
数据库