我想转换一个查询,例如:
SELECT BoolA, BoolB, BoolC, BoolD FROM MyTable;
进入一个位掩码,其中的位是由上面的值定义的。
例如,如果BoolA和BoolD为true,则我想要1001或9。
BoolA
BoolD
1001
9
我想到以下几点:
SELECT CASE WHEN BoolD THEN 2^0 ELSE 0 END + CASE WHEN BoolC THEN 2^1 ELSE 0 END + CASE WHEN BoolB THEN 2^2 ELSE 0 END + CASE WHEN BoolA THEN 2^3 ELSE 0 END FROM MyTable;
但是我不确定这是否是最好的方法,而且看起来很冗长。是否有捷径可寻?
对于位掩码,类型 bitstring 将是更好的选择。然后可能看起来像这样:
bitstring
SELECT BoolD::int::bit || BoolC::int::bit || BoolB::int::bit || BoolA::int::bit FROM tbl;
TRUE皈依1,FALSE对0。您可以简单地将位连接为位串。
TRUE
1
FALSE
0
看来您需要一个integer结果-有一个简单而快速的方法:
integer
SELECT (BoolD::int::bit || BoolC::int::bit || BoolB::int::bit || BoolA::int::bit)::bit(4)::int FROM tbl;
请务必阅读本手册“位字符串函数和运算符”一章中的详细说明。
我提出了另外两个想法,并结合了10k行的快速测试/参考来总结所有内容。
测试设置:
CREATE TEMP TABLE t (boola bool, boolb bool, boolc bool, boold bool); INSERT INTO t SELECT random()::int::bool , random()::int::bool , random()::int::bool , random()::int::bool FROM generate_series(1,10000);
演示:
SELECT CASE WHEN boold THEN 1 ELSE 0 END + (CASE WHEN boolc THEN 1 ELSE 0 END << 1) + (CASE WHEN boolb THEN 1 ELSE 0 END << 2) + (CASE WHEN boola THEN 1 ELSE 0 END << 3) AS andriy , boold::int + (boolc::int << 1) + (boolb::int << 2) + (boola::int << 3) AS mike , (boola::int::bit || boolb::int::bit || boolc::int::bit || boold::int::bit)::bit(4)::int AS erwin1 , boold::int | (boolc::int << 1) | (boolb::int << 2) | (boola::int << 3) AS erwin2 , ((( boola::int << 1) | boolb::int << 1) | boolc::int << 1) | boold::int AS erwin3 FROM t LIMIT 15
您也可以使用按位或| 而不是+运算符。 单独的测试运行 显示出这五种方法的基本 相同的性能 。
|
+