https://www.tiyee.net/post/178.html
获得MySQL中不同位的数量
SELECT BIT_COUNT( CONV( '001011', 2, 10 ) ^ CONV( '001111', 2, 10 ) )
SELECT BIT_COUNT( CONV( '001011', 2, 10 ) ^ CONV( '001111', 2, 10 ) )
https://blog.csdn.net/hhj13978064496/article/details/90379886
SELECT data_code,data_value,bin(data_value) as 二进制 FROM tb_ceshi_data
where data_value & 8
截止目前我们已经学习了MySQL的三种运算符:算术运算符、比较运算符、逻辑运算符。三者有一个共同点都是针对字符型、表达式和十进制的数字。
那有没有一种专门为二进制数字提供的运算符呢?这就是本问题的主题:位运算符。
先看看位运算符的定义:
位运算符用来对二进制字节中的位进行位移或者测试处理,MySQL中提供的位运算符有按位或(|)、按位与(&)、按位异或(^)、按位左移(<<)、按位右移(>>)、按位取反(~)等运算符。
接下来就通过案例的方式来逐一解开这六类位运算符的什么面纱。
【1】按位或:|
select 3|8,4|7|10;
如何从十进制的角度看待位运算的结果是无法解释的。所以我们先要把参与操作的数字转化为二进制形式。如下:
【结论】
3|8就是两个二进制数0011与1000进行按位或的计算,对应的二进制位有一个或两个为1,运算结果为1,否则为0。所以,3|8的结果是1011,转化为十进制就是11。同理4|7得到0111,再与1010进行按位或得到1111,即为十进制数字15。
【2】按位与:&
select 3&8,4&7&10;
规则:进行按位与的计算,对应的二进制位有两个为1,运算结果为1,否则为0。
所以我们可以自己得出结果:3&8 = 0,4&7&10 = 0。
【3】按位异或:^
select 38,47^10;
规则:进行按位异或的计算,对应的二进制位不相同时,运算结果为1,否则为0。
所以我们可以自己得出结果:3^8 = 11,4710 = 9。
【4】按位左移:<<
select 8<<2,10<<3;
规则:进行按位左移的功能是让指定二进制的所有位都左移指定的位数。并且在左移指定位数后,左边高位的数值被移出丢弃,右边地位空出的位置则用0补齐。
8<<2就是二进制数1000向左移动2位得到100000,即为十进制数32;10<<3就是二进制数1010向左移动3位得到1010000,即为十进制数80。
【5】按位右移:>>
select 8>>2,10>>3;
规则:进行按位右移与按位左移逻辑一致,只是移动的方向变成了右边,即丢地右边的位数。
8>>2变成了10,即为十进制数2;10>>3变成了1,即为十进制数1。
【6】按位取反:~
select 8,3&8;
规则:按位取反是针对一个十进制数对应的二进制位上的数字都进行取反操作,即0变成1,1变成0,之后再转化为十进制得到结果。
8得到的是:18446744073709551607;3&8则是18446744073709551607转化为二进制后与0011进行按位与计算,结果为3。总结
位运算符是针对二进制字节的操作;位运算符有六种类型;学习位运算符之前,必须要掌握十进制与二进制之间的互相转换;针对两个操作数的有:按位或、按位与、按位异或;针对一个操作数的有:按位左移、按位右移、按位取反。
& : 按位与,二进制位同时都为1的位设为1。
| : 按位或,二进制位有一个位为1就为1.
^ : 按位异或,对应位的二进制数不同时,对应位的结果才为1;如果两个对应位数都为0或者都为1,则对应位的结果为0。
原理
b = 3 转化为2进制为 11
b即是 110 与 11
将b中都为1的位设为1,位数不够的补0.即110 与 011
运算结果010,转化为十进制结果为2
应用场景
每个景点包含很多属性,例如适合旅游的月份,我们一般的做法可能有两种:
是增加一个varchar字段,每个月份之间用一个特殊符号分隔保存,例如:"1,2,22,65,7"
建立一个关系表,在这里不能使用1-12的数字来表示月份,而是使用1,2,4,8,16,32,64,128,512,1024,2048,4096来表示,如果是多个月份,可以相互组合相加,之后存储为一个值。
比如 1,10,12月份,就可以存储1+512+4096=4609,4096 这个值。
这个技巧适用于属性较少的一对多的场景,可以存储1个或者多个,太多的话还是推荐试用关系表。常用的属性有:月份,消息提醒类型,各种有限的类型组合等等。
使用技巧:
-- 添加一个分类 用 “|”
SELECT (4|2|1); --- = 7
-- 去掉一个分类,用“^”
SELECT 7 ^ 1;
-- 当我们需要查询某个月份的景点时,例如查询3月份的景点,可使用以下语句:
SELECT * FROM spots
WHERE month
& 4 = 4;
-- 当设置某个景点适合某个月份时,例如设置4325的景点适合2月份,可使用下面的语句:
UPDATE spots
SET month
= month
| 2 WHERE id
= 4325
-- 当取消设置某个景点的月份时,可使用下面的语句:
UPDATE spots
SETmonth
= month
^ 2 WHEREid
= 4325
-- 查询同时适合多个月份的数据,例如需要查询设置了11,12,1月份的景点,将其三个月份对应的数值加起来,结果为6145,然后使用这个数值进行查询:
SELECT * FROM spots
WHERE month
& 6145 = 6145
-- 查询只要适合,1,11,12月份其中一个月份的景点就行
SELECT * FROM spots
WHERE (month
& 4096 = 4096) or (month
& 2048 = 2048) or (month
& 1 = 1)