前言: 本週,公司有個需求,須要對前臺一個多選值進行存儲,實現過程當中,想過三種方案,在這裏記錄下。數據庫
在最開始,多選值只有兩個,就打算用兩個布爾值分開存儲的,實現和使用都很方便。可是接下來,給到的多選值多了不少,發現這樣的設計有很大的問題。spa
不符合數據庫範式、數據冗餘性大、不利於業務調整。設計
接下來,對設計進行了調整code
1. 將多選值設計成一個枚舉類, 帶有code值blog
public enum Hobby { READ("01", "讀書"), SING("02", "唱歌"), GAME("03", "遊戲"), SWIM("04", "游泳"), CYCLE("05", "騎車"); private String code; private String description; //...... }
2. 存儲時,將code以逗號分隔進行存儲, 如 01,03,04(讀書、遊戲、游泳)遊戲
3. 查詢時, 假設用戶想查詢愛好有讀書、游泳的人。那麼用戶的條件即: 01,04,此時SQL過濾條件爲:SELECT * FROM tb_user hobby WHERE LIKE '%01%04%'。 即利用like進行模糊查詢,將逗號用%號代替。ip
總結: 此方法適用於表的數據量不是很大的狀況, 由於查詢效率不高io
方案三(利用位運算):class
今天想到了一種更好的方案, 利用的是數據庫的「位」運算來實現效率
1. 將多選值設計成一個枚舉類,帶有權重標識
public enum Hobby { READ(1, "讀書"), SING(2, "唱歌"), GAME(4, "遊戲"), SWIM(8, "游泳"), CYCLE(16, "騎車"); private int weight; private String description; //...... s }
2. 存儲時,將用戶選擇的多選值,權重進行相加、將獲得的整型數值進行存儲。 如:讀書、遊戲、游泳, 權重和爲1 + 4 + 8 = 13, 即存儲13進入數據庫
3. 查詢時, 假設用戶想查詢愛好有讀書、游泳的人。那麼用戶的條件權重值爲1 + 4 = 5,此時SQL過濾條件爲:SELECT * FROM tb_user hobby WHERE hobby & 5 > 0。
總結: 此方案較爲簡單,存儲更加方便,查詢效率也高於方案二