枚举类状态做批量查询以及范围查询优化

文章目录

  • 前言
  • 问题
  • 目标
  • 现存的状态
  • 思路
    • 三大状态
    • 状态计算(1)
    • 状态计算(2)
  • 工具类
  • 示例

前言

往往项目中有一些类似于订单类的数据中有很多状态相关的流转操作,这些时候有可能因为某些业务逻辑要对状态进行范围查询或者多值匹配、排除之类的操作。

问题

在进行数据查询时由于过多的状态导致在查询一系列有关状态的数据时会包括或者排除很多状态值,造成代码书写复杂,并且会拖慢查询效率,例如如下的sql操作:

select * from table where state in ('init', 'reject', 'success')
or
select * from table where state not in ('init', 'reject', 'success')

目标

优化状态结构或者对状态进行分组汇总。

工作书写时减少必要的繁琐工作。

提高数据库的查询效率。

工具类通过将想要包括或者排除的状态作为参数,返回分组后的状态

现存的状态

目前存在的状态:

INIT("INIT","初始阶段"),
REAL_NAME("REAL_NAME","实名阶段"),
REAL_NAME_REJECT("REAL_NAME_REJECT","未实名"),
RISK("RISK", "风控阶段"),
RISK_REJECT("RISK_REJECT", "风控拒绝"),
RISK_FEATURE("RISK_FEATURE", "风控策略"),
RISK_WORKFLOW_SUBMIT("CASHBACK_RISK_WORKFLOW_SUBMIT", "风控工作流提交"),
RISK_WORKFLOW_QUERY("CASHBACK_RISK_WORKFLOW_QUERY", "风控工作流结果查询"),
RISK_FEATUR_REJECT("RISK_FEATURE_REJECT", "风控策略拒绝")

思路

三大状态

所有的状态总结来说订单存在三大状态:初始化 -> 过程中 -> 结束

数据库层面 在现有的数据库表中新增一列 pack_state ,用来存储 state 分组后的状态:

initprocessend

代码层面 根据业务查询 pack_state 或者 state

思路比较简单,分组情况少,但是结构和分组固定,有一定的局限性。比如不能随意组合,只能根据这三大状态进行查询,相当于缩小版的 state

状态计算(1)

通过对所有状态规定一个顺序,例如:

INIT("1","INIT","初始阶段"),
REAL_NAME("2","REAL_NAME","实名阶段"),
REAL_NAME_REJECT("3","REAL_NAME_REJECT","未实名"),
RISK("4","RISK", "风控阶段"),
RISK_REJECT("5","RISK_REJECT", "风控拒绝"),
RISK_FEATURE("6","RISK_FEATURE", "风控策略"),
RISK_WORKFLOW_SUBMIT("7","CASHBACK_RISK_WORKFLOW_SUBMIT", "风控工作流提交"),
RISK_WORKFLOW_QUERY("8","CASHBACK_RISK_WORKFLOW_QUERY", "风控工作流结果查询"),
RISK_FEATUR_REJECT("9","RISK_FEATURE_REJECT", "风控策略拒绝")

数据库层面创建数据库一列 pack_state ,类型为 bit(16) ,即状态类型的顺序则规定了自己在二进制的位置。具体表现为如下方式:

  • INIT(“1”,“INIT”,“初始阶段”) --> 0b0000 0000 0000 0001
  • RISK(“4”,“RISK”, “风控阶段”) --> 0b0000 0000 0000 1000

查询时如下操作:

where pack_state & #{type}

代码层面这些状态可以随意组合,写一个小工具来进行组合,传入的参数就是要查询的状态,根据顺序进行编排,例如:0b0000 0000 0000 1001 就是要查询 "init"、"risk" 类型的数据。

延伸拓展若要查询非 "init"、"risk" 则对该类型进行排除

状态计算(2)

实现方式同 状态计算(1)。

数据库层面创建数据库一列 pack_state ,类型为 int() ,具体表示为如下方式:

  • CASHBACK_INIT(“1”,“INIT”,“初始阶段(暂未使用)”) --> 1
  • CASHBACK_RISK(“4”,“RISK”, “风控阶段”) --> 8

查询时利用mysql的函数:

# 传入二进制
where BIN(pack_state) & #{type}
#或者
# 传入十进制
where BIN(pack_state) & BIN(#{type})

代码层面同样可以随意组合,写一个小工具来进行组合,传入的参数就是要查询的状态,根据顺序进行编排,例如:0b0000 0000 0000 0000 0000 0000 0000 1001 那么返回的结果就是 9, 就是要查询 "init"、"risk" 类型的数据。

注意:返回的结果和状态的排序结果没有不然联系,仅仅是根据需要查询的状态组成的二进制转换成的十进制数罢了。

这两种状态计算的好处就是能够将之前的范围查询和多值匹配变成了定值使用位运算查询,不好的一点就是需要做文档备注维护列内容的描述,列的值不是很好理解,没有做到一目了然。

有另外一种解法就是将顺序和状态维护在字典或者数据库里面,便于找对一个关系。

工具类

package com.xiaoju.manhattan.global.credit.card.process;

import java.util.Arrays;
import java.util.stream.Collectors;

public class StateConvertUtil {

    public static void main(String[] args) {
        System.out.println(genBinCodeByStatusList(CashBackStateEnum.CASHBACK_INIT, CashBackStateEnum.CASHBACK_RISK));
        System.out.println(" =======================================");
        System.out.println(genBinCodeByStatusList(false, CashBackStateEnum.CASHBACK_INIT, CashBackStateEnum.CASHBACK_RISK));
        System.out.println(" =======================================");
        System.out.println(genDecCodeByStatusList(CashBackStateEnum.CASHBACK_INIT, CashBackStateEnum.CASHBACK_RISK));
        System.out.println(" =======================================");
        System.out.println(genDecCodeByStatusList(false, CashBackStateEnum.CASHBACK_INIT, CashBackStateEnum.CASHBACK_RISK));
        System.out.println(" =======================================");
    }


    /**
     * @Author: zhou
     * @Description: 工具类日志打印
     * @Date: 2024/1/16 11:17 AM
     * @Param: include  包含or排除
     * @Param: binary   二进制or十进制
     * @Param: cashBackStateEnums
     * @return: void
     */
    private static void logSys(boolean include, boolean binary, CashBackStateEnum[] cashBackStateEnums) {
        System.out.printf("是否包含:%s,类型:%s,类型:%s%n", include? "是":"否", binary? "二进制":"十进制", Arrays.stream(cashBackStateEnums).map(item -> item.code).collect(Collectors.joining(",")));
    }


    /**
     * @Author: zhou
     * @Description: 根据配置和状态枚举生成十进制code
     * @Date: 2024/1/16 11:13 AM
     * @Param: cashBackStateEnums 状态枚举
     * @return: java.lang.String
     */
    public static String genDecCodeByStatusList(CashBackStateEnum ... cashBackStateEnums) {
        logSys(true, false, cashBackStateEnums);
        return genCodeByStatusList(true, false, cashBackStateEnums);
    }

    /**
     * @Author: zhou
     * @Description: 根据配置和状态枚举生成十进制code
     * @Date: 2024/1/16 11:19 AM
     * @Param: include  包含or排除
     * @Param: cashBackStateEnums   状态枚举
     * @return: java.lang.String
     */
    public static String genDecCodeByStatusList(boolean include, CashBackStateEnum ... cashBackStateEnums) {
        logSys(include, true, cashBackStateEnums);
        return genCodeByStatusList(include, false, cashBackStateEnums);
    }

    /**
     * @Author: zhou
     * @Description: 根据配置和状态枚举生成二进制code
     * @Date: 2024/1/16 11:20 AM
     * @Param: cashBackStateEnums   状态枚举
     * @return: java.lang.String
     */
    public static String genBinCodeByStatusList(CashBackStateEnum ... cashBackStateEnums) {
        logSys(true, true, cashBackStateEnums);
        return genCodeByStatusList(true, true, cashBackStateEnums);
    }


    /**
     * @Author: zhou
     * @Description: 根据配置和状态枚举生成二进制code
     * @Date: 2024/1/16 11:16 AM
     * @Param: include  包含or排除
     * @Param: cashBackStateEnums   状态枚举
     * @return: java.lang.String
     */
    public static String genBinCodeByStatusList(boolean include, CashBackStateEnum... cashBackStateEnums) {
        logSys(include, true, cashBackStateEnums);
        return genCodeByStatusList(include, true, cashBackStateEnums);
    }

    /**
     * @Author: zhou
     * @Description: 根据配置和状态枚举生成code
     * @Date: 2024/1/16 11:12 AM
     * @Param: include  包含or排除
     * @Param: binary   二进制or十进制
     * @Param: cashBackStateEnums   状态枚举
     * @return: java.lang.String
     */
    private static String genCodeByStatusList(Boolean include, Boolean binary, CashBackStateEnum ... cashBackStateEnums) {
        int decResult = 0;
        for (CashBackStateEnum anEnum : cashBackStateEnums) {
            decResult += 1 << anEnum.order - 1;
        }
        System.out.println("结果:" + decResult);
        if (binary ==null || binary) {
            System.out.println("结果转二进制:" + Integer.toBinaryString(decResult));
        }
        if (include == null || !include) {
            decResult = ~decResult;
            System.out.println("结果取反:" + decResult);
            if (binary == null || binary) {
                System.out.printf("结果取反二进制:%s,长度:%d%n", Integer.toBinaryString(decResult), Integer.toBinaryString(decResult).length());
            }
        }
        return (binary == null || binary)? Integer.toBinaryString(decResult):Integer.toString(decResult);
    }


    enum StateEnum {
        INIT(1, "INIT", "初始阶段(暂未使用)"),
        REAL_NAME(2, "REAL_NAME", "实名阶段"),
        REAL_NAME_REJECT(3, "REAL_NAME_REJECT", "未实名"),
        RISK(4, "RISK", "风控阶段"),
        RISK_REJECT(5, "RISK_REJECT", "风控拒绝"),
        RISK_FEATURE(6, "RISK_FEATURE", "风控策略"),
        RISK_WORKFLOW_SUBMIT(7, "CASHBACK_RISK_WORKFLOW_SUBMIT", "风控工作流提交"),
        RISK_WORKFLOW_QUERY(8, "CASHBACK_RISK_WORKFLOW_QUERY", "风控工作流结果查询"),
        RISK_FEATUR_REJECT(9, "RISK_FEATURE_REJECT", "风控策略拒绝");

        final int order;
        final String code;
        final String desc;

        CashBackStateEnum(int order, String code, String desc) {
            this.order = order;
            this.code = code;
            this.desc = desc;
        }

        public static StateEnum safeValueOf(String code) {
            return Arrays.stream(StateEnum.values()).filter(
                    state -> state.getCode().equals(code)
            ).findFirst().orElse(null);
        }
    }
}

示例

对状态计算(1)做一个简单的示例:

  • 针对表改造新增列 pack_state ,类型为 bit(16)
  • 根据对应关系我们存入 init、 risk、 risk_reject 状态的三条数据。
  • 我们要查询包含这三个状态的数据,需要根据工具类生成二进制的code值为 11001
  • 查询的sql: select * from table where pack_state & #{pack_state}
  • 查询的结果可以得到 init、 risk、 risk_reject 状态的三条数据。
    在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/325581.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

SpringBoot集成Mybatis Plus【附源码】

1. 背景 作为SpringBoot集成中间件其中的一篇文章吧&#xff0c;既然打算出这么一个系列了&#xff0c;争取做到虽小却全&#xff0c;又精又美的一个系列吧。 Mybatis Plus作为我入行以来&#xff0c;一直接触的一个中间件&#xff0c;也必须集成一下。同时也为初学者带来一些…

大数据传输慢的真正原因与解决方案

随着企业数据不断增长&#xff0c;大数据传输已成为一项至关重要的任务。然而&#xff0c;许多企业在处理大数据传输时频繁遭遇传输速度慢的问题。本文将深入探讨大数据传输速度慢的根本原因&#xff0c;并提供一些切实有效的解决方案。 大数据传输在企业中的重要性不言而喻&am…

旧衣回收小程序搭建:降低企业成本,提高回收效率!

在人们环保意识提升下&#xff0c;旧衣回收行业受到了大众的关注&#xff0c;同时旧衣回收具有门槛低、利润大的优势。在我国&#xff0c;回收行业不仅帮助普通人就业获利&#xff0c;还对环保做出了较大贡献。因此&#xff0c;旧衣回收行业成为了当下的热门商业模式&#xff0…

行为树(Behavior Trees)

行为树&#xff08;Behavior Trees&#xff09;是一种在游戏开发中广泛使用的AI设计模式&#xff0c;主要用于描述AI的行为和决策过程&#xff0c;实现更加智能和自然的游戏AI。它由多个节点组成&#xff0c;每个节点代表一个行为或决策&#xff0c;按照特定的方式连接在一起&a…

智能助手的巅峰对决:ChatGPT对阵文心一言

在人工智能的世界里&#xff0c;ChatGPT与文心一言都是备受瞩目的明星产品。它们凭借先进的技术和强大的性能&#xff0c;吸引了大量用户的关注。但究竟哪一个在智能回复、语言准确性、知识库丰富度等方面更胜一筹呢&#xff1f;下面就让我们一探究竟。 首先来谈谈智能回复能力…

数据结构学习 jz41 数据流中的中位数

关键词&#xff1a;排序 大顶堆 小顶堆 题目&#xff1a;数据流中的中位数 这道题我没有想到用两个堆来做。 思路&#xff1a; 关键&#xff1a;维护两个堆&#xff0c;一个大顶堆一个小顶堆。 大顶堆&#xff1a;装较小的那一半的数&#xff0c;它的顶就是较小那一半数的最…

淘宝搜索引擎API接口关键字搜索商品列表获取商品详情价格评论销量API

item_search-按关键字搜索淘宝商品 公共参数 查看API完整文档 名称类型必须描述keyString是调用key&#xff08;必须以GET方式拼接在URL中&#xff09;secretString是调用密钥api_nameString是API接口名称&#xff08;包括在请求地址中&#xff09;[item_search,item_get,it…

如何在企业微信开发者中心使用内网穿透工具回调本地接口服务

文章目录 1. Windows安装Cpolar2. 创建Cpolar域名3. 创建企业微信应用4. 定义回调本地接口5. 回调和可信域名接口校验6. 设置固定Cpolar域名7. 使用固定域名校验 企业微信开发者在应用的开发测试阶段&#xff0c;应用服务通常是部署在开发环境&#xff0c;在有数据回调的开发场…

Mysql root 密码重置详解

文章目录 1 概述1.1 前言1.2 mysql 版本查询 2 windows 操作系统2.1 mysql 8 及以上版本2.1.1 关闭 mysql 服务2.1.2 通过无认证方式启动 mysql2.1.3 新开窗口&#xff0c;登录 mysql&#xff0c;重置密码 1 概述 1.1 前言 不同的操作系统&#xff08;如&#xff1a;windows、…

Eureka 本机集群实现

距离上次发布博客已经一年多了&#xff0c;主要就是因为考研&#xff0c;没时间学习技术的内容&#xff0c;现在有时间继续完成关于代码方面的心得&#xff0c;希望跟大家分享。 今天在做一个 Eureka 的集群实现&#xff0c;我是在本电脑上跑的&#xff0c;感觉这个挺有意思&a…

AI智能化办公:巧用ChatGPT高效搞定Excel数据分析

文章目录 1. 自动提取关键信息2. 自动生成分析报告3. 自动回答问题4. 自动生成图表《巧用ChatGPT高效搞定Excel数据分析》关键点内容简介作者简介 《AI智能化办公&#xff1a;ChatGPT使用方法与技巧从入门到精通》图书特色内容简介作者简介 随着人工智能技术的不断发展&#xf…

【ELK 学习】ElasticSearch

ELK&#xff1a;ElasticSearch存储&#xff0c;Logstash收集&#xff0c;Kibana展示 版本较多&#xff0c;使用时需要版本匹配&#xff0c;还需要和mysql版本匹配&#xff08;elastic官网给了版本对应关系&#xff09; 本次使用的版本es6.8.12 filebeat 轻量级的数据收集工具 …

web前端第二次作业

1&#xff0c;计算用户指定的数值内的奇数和 效果运行图&#xff1a; 代码&#xff1a; <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><title>计算用户指定的数值内的奇数和</title> </head>…

【Dynamo学习笔记】基础入门

目录 前言1 Dynamo的界面2 节点的操作3 几何形体的创建与编辑3.1 几何形体的创建3.1.1 直线3.1.2 圆形3.1.3 多边形3.1.4 长方体3.1.5 球体 3.2 几何形体的编辑3.2.1 坐标点的平移复制3.2.2 几何形体的平移复制3.2.3 几何形体的镜像复制3.2.4 几何形体的旋转复制3.2.5 几何形体…

数字前端/FPGA设计——握手与反压问题

声明&#xff1a;本文来自0431大小回 前言&#xff1a;在芯片设计或者FPGA设计过程中&#xff0c;流水设计是经常用到的&#xff0c;但是考虑数据安全性&#xff0c;需要与前后级模块进行握手通信&#xff0c;这时候就需要对流水数据进行反压处理&#xff0c;本文将具体介绍握手…

尺寸公差 DTAS3D产品功能介绍

DTAS 3D (Dimensional Tolerance Analysis System 3D)基于蒙特卡洛原理&#xff0c;按照产品的公差及装配关系进行建模&#xff0c;然后进行解析、仿真计算&#xff0c;最终预测产品设计是否能够满足其关键尺寸要求&#xff0c;同时预测产品合格率&#xff0c;并进行根源分析。…

【NI国产替代】NI‑9232,3通道,102.4 kS/s/ch,±30 V,C系列声音与振动输入模块

3通道&#xff0c;102.4 kS/s/ch&#xff0c;30 V&#xff0c;C系列声音与振动输入模块 NI‑9232可以测量来自集成电子压电(IEPE)和非IEPE传感器的信号&#xff0c;例如加速度计、转速计和接近式探针。 NI‑9232还可兼容智能TEDS传感器。\n\nNI‑9232集成了软件可选的AC/DC耦合…

Fpga开发笔记(二):高云FPGA发开发软件Gowin和高云fpga基本开发过程

若该文为原创文章&#xff0c;转载请注明原文出处 本文章博客地址&#xff1a;https://hpzwl.blog.csdn.net/article/details/135620590 红胖子网络科技博文大全&#xff1a;开发技术集合&#xff08;包含Qt实用技术、树莓派、三维、OpenCV、OpenGL、ffmpeg、OSG、单片机、软硬…

spring Security源码分析-13种过滤器详解

13种核心过滤器 spring security的13个核心过滤器(按执行顺序陈列): WebAsyncManagerIntegrationFilterSecurityContextPersistenceFilterHeaderWriterFilterLogoutFilterUsernamePasswordAuthenticationFilterDefaultLoginPageGeneratingFilterDefaultLogoutPageGeneratingF…

Windows Server 2019配置DNS服务器

正文共&#xff1a;1234 字 31 图&#xff0c;预估阅读时间&#xff1a;1 分钟 我们在给Windows Server添加角色和功能时&#xff0c;会发现有一项“远程桌面服务安装”&#xff0c;它的介绍为“为虚拟桌面基础结构&#xff08;Virtual Desktop Infrastructure&#xff0c;VDI&…