mysql contains函数_多属性、多分类MySQL模式设计
一、導(dǎo)讀
這是來自B乎的一個問答。 當(dāng)數(shù)據(jù)同時具備多個屬性/分類時,改如何設(shè)計表結(jié)構(gòu)和查詢?
二、需求描述
我偶爾也會逛逛B乎,看到一些感興趣的話題也會回復(fù)下。 有一次,看到這樣的一個話題:
鏈接:https://www.zhihu.com/questio...
[mysql] 當(dāng)數(shù)據(jù)同時屬于多個分類時,該怎么查詢?
分類cate字段為[1,2,3,4,5] ,假如要查詢滿足分類’2’和’5′ 的數(shù)據(jù)該怎么查詢? 我嘗試過用 cate like ‘%2%’ AND cate like ‘%5%’去查。 想問有沒有更好的辦法,我這樣寫數(shù)據(jù)少了還好,多了根本沒法查,效率太低了。
恰好我以前做過類似的業(yè)務(wù)需求設(shè)計,所以就回復(fù)了這個問題。
三、模式設(shè)計思路
這個需求可以有幾種不同的解決思路,我們分別展開說一下。
(一)用bit數(shù)據(jù)類型
大概思路如下:
1、物品屬性列c1 用bit數(shù)據(jù)類型 來表示,也就是只有0、1兩種取值
2、當(dāng)物品屬性具備某個分類屬性時,其值為1,否則為0
3、假如共有5個分類,當(dāng)物品擁有全部分類屬性時,則其值為11111,若其不具備第3個分類屬性,則其值為11011,在數(shù)據(jù)庫中轉(zhuǎn)成十進制存儲
4、上述兩種情況下,將二進制轉(zhuǎn)換成十進制表示,即分別是31和27
5、然后,只需要對該列用十進制值進行查詢比對就行 6、現(xiàn)在如果想判斷是否同時具備2、5兩個分類屬性時,其二進制表示為01001,轉(zhuǎn)成十進制為9,只需要用條件 where c1=9 即可
我們來演示一下:
[root@yejr.me] [zhishutang]>show create table t_bitG*************************** 1. row ***************************Table: t_bit Create Table: CREATE TABLE `t_bit` (`id` int(10) unsigned NOT NULL AUTO_INCREMENT,`c1` int(10) unsigned NOT NULL DEFAULT '0',`c2` varchar(10) NOT NULL DEFAULT '',PRIMARY KEY (`id`),KEY `c1` (`c1`) ) ENGINE=InnoDB;insert into t_bit select 0,conv(00001, 2, 10), 'item1'; insert into t_bit select 0,conv(00011, 2, 10), 'item2'; insert into t_bit select 0,conv(00111, 2, 10), 'item3'; insert into t_bit select 0,conv(01111, 2, 10), 'item4'; insert into t_bit select 0,conv(11111, 2, 10), 'item5'; insert into t_bit select 0,conv(10111, 2, 10), 'item6'; insert into t_bit select 0,conv(11011, 2, 10), 'item7'; insert into t_bit select 0,conv(11101, 2, 10), 'item8'; insert into t_bit select 0,conv(11110, 2, 10), 'item9';[root@yejr.me] [zhishutang]>select * from t_bit; +----+----+-------+ | id | c1 | c2 | +----+----+-------+ | 1 | 1 | item1 | | 2 | 3 | item2 | | 3 | 7 | item3 | | 4 | 15 | item4 | | 5 | 31 | item5 | | 6 | 23 | item6 | | 7 | 27 | item7 | | 8 | 29 | item8 | | 9 | 30 | item9 | +----+----+-------+[root@yejr.me] [zhishutang]>select * from t_bit where c1 = conv(11011,2,10); +----+----+-------+ | id | c1 | c2 | +----+----+-------+ | 7 | 27 | item7 | +----+----+-------+#同時我們也注意到這個SQL是可以正常使用索引的 [root@yejr.me] [zhishutang]>desc select * from t_bit where c1 = conv(11011,2,10)G *************************** 1. row ***************************id: 1select_type: SIMPLEtable: t_bitpartitions: NULLtype: ref possible_keys: c1key: c1key_len: 4ref: constrows: 1filtered: 100.00Extra: NULL下面兩種方法是B乎網(wǎng)友的回復(fù),大家也可以參考下。
1、用JSON數(shù)據(jù)類型,然后利用JSON_CONTAINS()函數(shù)進行查詢
2、用SET數(shù)據(jù)類型,然后利用FIND_IN_SET()函數(shù)進行查詢
不過,JSON和SET這兩種數(shù)據(jù)類型都不方便加索引以及利用索引掃描,即便是用了5.7的JSON+虛擬列功能,索引效率也是比較低的。而支持JSON數(shù)據(jù)類型 多值索引(multi-valued Indexes) 也要8.0.17 以上版本才支持。
四、總結(jié)
這樣看來,總的來說,用二進制轉(zhuǎn)十進制方式來解決本案例需求更為高效,也歡迎提出更多方案思路。
延伸閱讀
- Multi-Valued Indexes
- The SET Type
總結(jié)
以上是生活随笔為你收集整理的mysql contains函数_多属性、多分类MySQL模式设计的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: latex转word_Latex与wor
- 下一篇: md5后得到的32位字符串存储到mysq