使用位運算,處理資料庫中的"多選狀態標識"
- 引言【摘自其他文章】:
最近在對公司以前的一個專案進行調整時發現,資料庫中有很多表示“多選狀態標識”的欄位。“多選狀態標識”可能描述的並不十分準確,在這裡用我們專案中的幾個例子進行說明一下。
例一:表示某個商家是否支援多種會員卡打折(如有金卡、銀卡、其他卡等),專案中的以往的做法是:在每條商家記錄中為每種會員卡建立一個標誌位欄位。如圖:
其中藍色區域的三個整形欄位分別表示三種會員卡。當值為“1”時表示當前商家支援這種會員卡打折,反之“0”則表示不支援。
例二:表示系統字典表中某種型別方式,會在哪個功能模組中呼叫。如某種“支付方式”可能在“收銀模組”中會用到,在“結算模組”中也會用到。如圖:
用多欄位來表示“多選標識”存在一定的缺點:首先這種設定方式很明顯不符合資料庫設計第一正規化,增加了資料冗餘和儲存空間。再者,當業務發生變化時,不利於靈活調整。比如,增加了一種新的會員卡型別時,需要在資料表中增加一個新的欄位,以適應需求的變化。
因此,我們在重新審視資料庫設計時,我的一位同事提出了一種代替方式:將多個狀態標識欄位合併成一個欄位,並把這個欄位改成字串型,對多選狀態值以字串陣列的方式儲存(一個以逗號分隔的字串:“1,2,3”)。表的結構變成如下:
“MEMBERCARD”欄位中,當存在“1”時表示支援金卡打折,“2”時表示支援銀卡打折,“3”表示支援其他卡打折。
這樣調整的好處,不僅消除相同欄位的冗餘,而且當增加新的會員卡類別時,不需增加新的欄位。但帶來新的問題:在資料查詢時,需要對字串進行分隔。並且字串型別的欄位在查詢效率和儲存空間上不如整型欄位。
總的來說,上面調整的思路是正確的,但不夠自然。我後來考慮了一下,覺得可以用“位”來解決這個問題:二進位制的“位”本來就有表示狀態的作用。可以用下面各個位來分別表示不同種類的會員卡打折支援:
這樣,“MEMBERCARD”欄位仍採用整型。當某個商家支援金卡打折時,則儲存“1(0001)”,支援銀卡時,則儲存“2(0010)”,兩種都支援,則儲存“3(0011)”。其他類似。表結構如圖:
我們在編寫SQL語句時,只需要通過“位”的與運算,就能簡單的查詢出想要資料:
- //查詢支援金卡打折的商家資訊:
- select * from factory where MEMBERCARD & b'0001'
- 或者:
- select * from factory where MEMBERCARD & 1
- //查詢支援銀卡打折的商家資訊:
-
select * from factory where MEMBERCARD & b'0010'
- 或者:
- Select * from factory where MEMBERCARD & 2
通過這樣的處理方式既節省儲存空間,查詢時又簡單方便。以上sql語句為MySQL的語法,其他資料庫方法類似。並且“b'0010'”二進位制的表示方式的語法是在5.0以後的版本才有。
- 實際操作【實戰一把】:
CREATE TABLE `news`(
`id` int(11) NOT NULL AUTO_INCREMENT COMMENT '主鍵ID',
`title` varchar(20) NOT NULL COMMENT '文章標題',
`status` int(2) NOT NULL COMMENT '狀態 1:是否置頂;2:是否點贊;4:是否推薦',
PRIMARY KEY (`id`)
) ENGINE=MyISAM AUTO_INCREMENT=7 DEFAULT CHARSET=utf8;
資料表的原始資料:
【更新】status =置頂;
update news set status = status |1 where id =1
【更新】status =點贊; update news set status = status | 2 where id = 1
【更新】status =推薦; update news set status = status | 4 where id = 2
【選擇】status =推薦;
select *from news where status &4=4
【選擇】status =置頂&推薦&點贊;;
select *from news where status &7=7
【選擇】status =置頂&推薦;
select *from news where status &3=3
【選擇】status =不置頂&不推薦;
select *from news where status &1!=1and status &4!=4
【選擇】status =不置頂|不點贊;
select *from news where status &1!=1or status &2!=2
【更新某記錄】status =推薦,為不推薦;
update news set status = status ^4 where id =1
更新後:
- 後記【位運算】:
按位與運算
按位與運算子"&"是雙目運算子。
其功能是參與運算的兩數各對應的二進位相與。只有對應的兩個二進位均為1時,結果位才為1,否則為0。
參與運算的數以補碼方式出現。
例如:9&5可寫算式如下:
00001001(9的二進位制補碼)
&00000101(5的二進位制補碼)
00000001(1的二進位制補碼)
可見9&5=1。
按位與運算通常用來對某些位清0或保留某些位。
例如把a 的高八位清0,保留低八位,可作a&255運算(255的二進位制數為0000000011111111)。
按位或運算
按位或運算子“|”是雙目運算子。其功能是參與運算的兩數各對應的二進位相或。
只要對應的二個二進位有一個為1時,結果位就為1。參與運算的兩個數均以補碼出現。
例如:9|5可寫算式如下:
00001001
|00000101
00001101(十進位制為13)
可見9|5=13
按位異或運算
按位異或運算子“^”是雙目運算子。其功能是參與運算的兩數各對應的二進位相異或,當兩對應的二進位相異時,結果為1。
參與運算數仍以補碼出現,
例如9^5可寫成算式如下:
00001001
^00000101
00001100(十進位制為12)
求反運算
求反運算子~為單目運算子,具有右結合性。
其功能是對參與運算的數的各二進位按位求反。
例如~9的運算為:
~(0000000000001001)
結果為:1111111111110110
左移運算
左移運算子“<<”是雙目運算子。其功能把“<<”左邊的運算數的各二進位全部左移若干位,由“<<”右邊的數指定移動的位數,高位丟棄,低位補0。
例如:
a<<4
指把a的各二進位向左移動4位。
如a=00000011(十進位制3),左移4位後為00110000(十進位制48)。
右移運算
右移運算子“>>”是雙目運算子。
其功能是把“>>”左邊的運算數的各二進位全部右移若干位,“>>”右邊的數指定移動的位數。
例如:
設 a=15,
a>>2
表示把000001111右移為00000011(十進位制3)。
注意:對於有符號數,在右移時,符號位將隨同移動。當為正數時,最高位補0,而為負數時,符號位為1,
最高位是補0或是補1 取決於編譯系統的規定。Turbo C和很多系統規定為補1
相關推薦
使用位運算,處理資料庫中的"多選狀態標識"
引言【摘自其他文章】: 最近在對公司以前的一個專案進行調整時發現,資料庫中有很多表示“多選狀態標識”的欄位。“多選狀態標識”可能描述的並不十分準確,在這裡用我們專案中的幾個例子進行說明一下。 例一:表示某個商家是否支援多種會員卡打折(如有金卡
位運算,處理前臺多選值
scrip sin 分隔 sel 但是 接下來 條件 記錄 讀書 前言: 本周,公司有個需求,需要對前臺一個多選值進行存儲,實現過程中,想過三種方案,在這裏記錄下。 方案一(使用多個布爾值): 在最開始,多選值只有兩個,就打算用兩個布爾值分開存儲的,實現和使用都很
SQL 一個使用者表中有一個積分欄位,假如資料庫中有100多萬個使用者,若要在每年第一天凌晨將積分清零,你將考慮什麼,你將想什麼辦法解決?
alter table drop column score; alter table add colunm score int; 可能會很快,但是需要試驗,試驗
iOS藍牙通信數據處理,位運算,數據的大小端轉換
make 位數 存儲 大小端模式 計算 取出 sign nsstring nta 目的 轉載自:http://blog.csdn.net/remember_17/article/details/77337534?locationNum=10&fps=1 在藍牙項目的
http協議,阻塞IO,非阻塞IO,IO多路複用,位運算,select方法
HTTP請求 Request 請求格式: 請求行 GET / HTTP/1.1 請求種類  
python讀取xml資料庫中表內所有資料,獲取資料庫中所有表的欄位名稱
工作中需要讀取指定xml資料庫中的資料以及 表所需欄位名,所以在已有例子中改進實現: xml 資料庫 xmldabase.xml: <database> <manifest> <pair key="schema_major_vsn" v
【小家java】Java中二進位制與位運算(“^,&,>>,>>>”),使用移位演算法寫一個流水號生成器(訂單號生成器)
相關閱讀 每篇一句 高樓大廈,都是平地起的。 整個java體系,其實就是一本祕籍,那就是:java基礎! (基礎如果打的紮實,在實際開發工作中會帶來極大的助益) 二進位制 二進位制是計算技術中廣泛採用的一種數制。二進位制資料是用0和1兩個數碼來表示的
使用github作為maven倉庫存放發布自己的jar包依賴 實現多個項目公共部分代碼的集中,避免團隊中多個項目之間代碼的復制粘貼
地址 oba post 直接 bubuko http tps hub 之間 使用github作為maven倉庫存放發布自己的jar包依賴 實現多個項目公共部分代碼的集中,避免團隊中多個項目之間代碼的復制粘貼。 1、首先在本地maven位置的配置文件setting.xml(沒
zabbix監控添加主機,添加模板,處理圖形中的亂碼,自動發現
zabbix添加主機 添加模板 處理圖形中亂碼 自動發現 添加主機 優先添加主機群組,配置-添加主機群組主機-添加主機-群組-選擇剛剛創建的 群組,ip地址填寫客戶端IP, 添加自定義模板, 模板-添加-創建主機名-添加到組添加一個模板名稱aming 在模板下選擇一個想要監控的的項目,復制過來
主動模式和被動模式,添加監控主機,添加自定義模板,處理圖形中的亂碼,自動發現
zabbix主動模式和被動模式 主動或者被動是相對客戶端來講的被動模式,服務端會主動連接客戶端獲取監控項目數據,客戶端被動地接受連接,並把監控信息傳遞給服務端主動模式,客戶端會主動把監控數據匯報給服務端,服務端只負責接收即可。當客戶端數量非常多時,建議使用主動模式,這樣可以降低服務端的壓力。服務端有公網ip,
VS2013 c++連結資料庫,應用儲存過程,向資料庫中寫入資料
// ConsoleApplication1.cpp : 定義控制檯應用程式的入口點。 // #include "stdafx.h" #include "iomanip" using namespace std; #import "c:\Program Files\Common Files\S
JDBC上關於資料庫中多表操作一對多關係和多對多關係的實現方法--轉
原文地址---- https://www.cnblogs.com/pangguoming/p/7028322.html 黑馬程式設計師 我們知道,在設計一個Java bean的時候,要把這些BEAN 的資料存放在資料庫中的表結構,然而這些資料庫中的表直接又有些特殊
C# WPF DataGrid使用,包括隔行多選
C# WPF DataGrid使用,包括隔行多選 xaml cs xaml <ScrollViewer VerticalAlignment="Stretch" x:Name="scro
以單例模式為例,在Idea中多執行緒debug
我們以單例模式的懶漢式在idea中進行多執行緒debug 一是可以學習多執行緒debug,二是可以瞭解懶漢式的執行緒不安全的原因 首先我們建立一個單例懶漢式,然後建立兩個執行緒 程式碼如下: 然後 進行多執行緒debug,來干預懶漢式的執行順序
位運算,自低(右)向高(左)逐個地將數位1轉置為0
對任意整數n,不妨設其最低(右)的數位對應2^k,於是n的二進位制展開應該如下: x x ... x 1 0 0 ... 0 其中最右邊第一次1出現時,數位x可能是0或1,而最低的k+1位必然是“1 0 0 ... 0” ,即數位1
SQL中的where條件,在資料庫中提取與應用淺析
1 問題描述 一條SQL,在資料庫中是如何執行的呢?相信很多人都會對這個問題比較感興趣。當然,要完整描述一條SQL在資料庫中的生命週期,這是一個非常巨大的問題,涵蓋了SQL的詞法解析、語法解析、許可權檢查、查詢優化、SQL執行等一系列的步驟,簡短的篇幅是絕對無
關於c語言的位運算&,|,^(看懂漢字的都能看懂)
其中|,&可以當作邏輯運算子,當|,&當成邏輯運算子時,與||,&&的用法基本相似,&&,||運算時會當前面的表示式能夠決定整個表示式,則不進行對後面的判斷,如:1&&1,1||0,當表示式前面的已經決定了整個表
轉: SQL中的where條件,在資料庫中提取與應用淺析
SQL中的where條件,在資料庫中提取與應用淺析 http://hedengcheng.com/?p=577 1問題描述 一條SQL,在資料庫中是如何執行的呢?相信很多人都會對這個問題比較感興趣。當然,要完整描述一條SQL在資料庫中的生命週期,這是一個非常巨大的問題, 涵蓋了SQL的詞法解析、語
bzoj3832[Poi2014]Rally(set,bitset,位運算,拓撲排序,堆,線段樹)
傳送門:https://www.lydsy.com/JudgeOnline/problem.php?id=3832 Description 給定一個N個點M條邊的有向無環圖,每條邊長度都是1。 請找到一個點,使得刪掉這個點後剩餘的圖中的最長路徑最短。 Input 第一行包含兩個正
Codeforces Round #312 (Div. 2) (第三題是位運算,好題)
分析:從0座標分開,負半軸一個數組,正半軸一個數組,來記錄果樹的左邊和數量,可以用結構體陣列來儲存資料,其中少的一個半軸上的果樹肯定會全被採光,而多的一邊樹上會多采一棵樹。 struct p{ int num,x; } p neg[105],pos[105];這樣表