教你巧用mysql位運算解決多選值存儲的問題
一.問題場景
工作中經常遇到多選值存儲問題,例如:用戶有多種認證方式,密碼認證、短信認證、掃碼認證等,一個用戶可能只開啟了其中某幾種認證方式。
二. 場景分析
比較容易理解的兩種實現(xiàn)方式,多字段存儲、單個字段拼接存儲。
1.多字段存儲
每種認證方式用一個字段存儲,0表示未開啟,1表示已開啟。
缺點:每增加一種認證方式都需要添加一個表字段,擴展性差。
2.單字段拼接
單字段存儲,已開啟的認證方式用逗號(或其他分割符)拼接。例如:開始了密碼認證和短信認證,則存儲為:密碼認證,短信認證。
缺點:不利于查詢,需要使用模糊查詢,搞不好會影響性能。
三.巧用位運算
1.概述
參考Linux權限控制思路,將每種認證方式對應到二進制位中,例如:密碼認證–10000000,短信認證–01000000,掃碼認證–00100000,然后將其轉換成10進制,密碼認證–1, 短信認證–2,掃碼認證–4。Mysql存儲時使用單字段(auth_method)int類型存儲,如果開啟了多種認證方式將多種認證方式對應的枚舉數(shù)值相加后存儲,例如開啟了密碼認證和短信認證,則存儲為3(1+2)。
2.sql查詢
## 例1:判斷用戶是否開啟了密碼認證--1 (滿足條件時返回查詢結果,沒有滿足條件時返回為空) Select * from user where auth_method & 1; ## 例2:判斷用戶是否開啟了密碼認證 + 短信認證 (1+2) Select * from user where auth_method & 3; ## 例2:判斷用戶是否開啟了密碼認證 + 短信認證 + 掃碼認證 (1+2+4) Select * from user where auth_method & 7;
3.Java解析與計算
import com.google.common.collect.Lists; import lombok.Getter; import org.springframework.util.CollectionUtils; import java.util.Arrays; import java.util.List; @Getter public enum AuthMethodEnum { PASSWORD(1, "密碼認證"), SMS(2, "短信認證"), QR_CODE(4, "掃碼認證"); private Integer method; private String name; AuthMethodEnum(Integer method, String name) { this.method = method; this.name = name; } /** * 將mysql存儲值解析成多種認證方式 * @param method * @return */ public static List<Integer> parseAuthMethod(Integer method) { List<Integer> list = Lists.newArrayList(); if (null == method) { return list; } AuthMethodEnum[] arr = AuthMethodEnum.values(); // 需要先將method從大到小排序 Arrays.sort(arr, (o1, o2) -> { if (o1.method > o2.method) { return -1; } else { return 0; } }); for (AuthMethodEnum e : arr) { if (method >= e.method) { list.add(e.method); method = method - e.method; } } return list; } /** * 將任意種認證方式計算后得到存儲值 * @param methods * @return */ public static Integer calculateAuthMethod(List<Integer> methods) { if (CollectionUtils.isEmpty(methods)) { return 0; } return methods.stream().mapToInt(p -> p).sum(); } public static void main(String[] args) { System.out.println(parseAuthMethod(8)); } }
4.總結
通過位運算的轉換,實現(xiàn)了單個字段存儲不同的認證狀態(tài),增加一個新的認證方式時只需要添加一個枚舉值。不僅可以節(jié)省存儲空間,大大增加了可擴展性,對性能幾乎沒有影響。
附MySQL的支持6種位運算
符號 | 含義 |
---|---|
a|b | 位或 |
a&b | 位與 |
a^b | 位異或 |
~a | 位取反 |
a<<b | 位左移 |
a>>b | 位右移 |
總結
到此這篇關于教你巧用mysql位運算解決多選值存儲問題的文章就介紹到這了,更多相關mysql位運算解決多選值存儲內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
相關文章
mysql技巧:提高插入數(shù)據(jù)(添加記錄)的速度
這篇文章主要介紹了mysql技巧:提高插入數(shù)據(jù)(添加記錄)的速度,需要的朋友可以參考下2014-12-12MySQL 8.0.19安裝詳細教程(windows 64位)
這篇文章主要介紹了MySQL 8.0.19安裝詳細教程(windows 64位),本文通過圖文并茂的形式給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下2020-10-10MySQL去重中distinct和group?by的區(qū)別淺析
今天無意中聽到有同事在討論,distinct和group by有什么區(qū)別,下面這篇文章主要給大家介紹了關于MySQL去重中distinct和group?by區(qū)別的相關資料,需要的朋友可以參考下2022-11-11MySQL實現(xiàn)批量插入測試數(shù)據(jù)的方式總結
在開發(fā)過程中經常需要一些測試數(shù)據(jù),?這個時候如果手敲的話,?十行二十行還好,?多了就很死亡了,?接下來介紹兩種常用的MySQL測試數(shù)據(jù)批量生成方式,希望對大家有所幫助2023-05-05Linux7.6二進制安裝Mysql8.0.27詳細操作步驟
大家好,本篇文章主要講的是Linux7.6二進制安裝Mysql8.0.27詳細操作步驟,感興趣的同學快來看一看吧,希望對你起到幫助2021-11-11MyEclipse連接Mysql數(shù)據(jù)庫的方法(一)
這篇文章主要介紹了MyEclipse連接Mysql數(shù)據(jù)庫的方法(一)的相關資料,非常實用,具有參考價值,需要的朋友可以參考下2016-05-05MySQL數(shù)據(jù)庫開啟、關閉、查看函數(shù)功能的方法
這篇文章主要介紹了MySQL數(shù)據(jù)庫開啟、關閉、查看函數(shù)功能的方法,本文為解決一個錯誤總結而來,錯誤信息本文一同給出,需要的朋友可以參考下2014-10-10mysql正確刪除數(shù)據(jù)的方法(drop,delete,truncate)
這篇文章主要給大家介紹了關于mysql正確刪除數(shù)據(jù)的相關資料,DELETE語句是MySQL中最常用的刪除數(shù)據(jù)的方式之一,但也有幾種其他方法來實現(xiàn),需要的朋友可以參考下2023-10-10Spring中的InitializingBean和SmartInitializingSingleton的區(qū)別詳解
這篇文章主要介紹了Spring中的InitializingBean和SmartInitializingSingleton的區(qū)別詳解,InitializingBean只有一個接口方法afterPropertiesSet(),在BeanFactory初始化完這個bean,并且把bean的參數(shù)都注入成功后調用一次afterPropertiesSet()方法,需要的朋友可以參考下2024-01-01