Sql 转换;总结旗帜“;回归本义
我必须使用一个数据库,其中包含一列Sql 转换;总结旗帜“;回归本义,sql,postgresql,flags,Sql,Postgresql,Flags,我必须使用一个数据库,其中包含一列change,指示与前一个相应条目相比,其他三列的更改方式。更改类型可以是new、removed或changed 这些类型分配了以下编号: column | a b c ----------+---------------------- new | 3 12 48 removed | 2 8 32 changed | 1 4 1
change
,指示与前一个相应条目相比,其他三列的更改方式。更改类型可以是new
、removed
或changed
这些类型分配了以下编号:
column | a b c
----------+----------------------
new | 3 12 48
removed | 2 8 32
changed | 1 4 16
change
列的内容是所有应用更改类型的总和,即,如果列a
被change
和b
删除,则change
列将为1+8=9。(总是有变化,即可以有1、2或3个总和。)
我的问题是:我想不出一个聪明的方法来将这个“汇总标志”转换回它的原始含义(部分问题是不知道谷歌要做什么)
我可以看出,如果change
是不均匀的,a
要么是new
要么是changed
;如果change>=48
,c
是new
加上可能的其他更改,否则change>=32
=>c被删除
加上可能的其他更改,依此类推。我可能会把它们放在一个巨大的逻辑查询中——但我相信一定有一个复杂的解决方案可以做到这一点
如果相关的话,我会使用PostgreSQL。该表大约有5000万行。您可以使用位操作。如果我理解正确:
select (case when col::bit(8) & B'00000011' then 'new'
when col::bit(8) & B'00000001' then 'changed'
when col::bit(8) & B'00000010' then 'removed'
end) as a_status,
(case when col::bit(8) & B'00001100' then 'new'
when col::bit(8) & B'00000100' then 'changed'
when col::bit(8) & B'00001000' then 'removed'
end) as b_status,
(case when col::bit(8) & B'00110000' then 'new'
when col::bit(8) & B'00010000' then 'changed'
when col::bit(8) & B'00100000' then 'removed'
end) as c_status
这可以通过将位AND运算符(
&
)与位移位(>
)结合使用来实现
以下查询返回表的所有记录,并在另外三列中分别更改为a、b和c:
select *,
case change & 3
when 1 then 'changed'
when 2 then 'removed'
when 3 then 'new'
end as change_to_a,
case (change >> 2) & 3
when 1 then 'changed'
when 2 then 'removed'
when 3 then 'new'
end as change_to_b,
case (change >> 4) & 3
when 1 then 'changed'
when 2 then 'removed'
when 3 then 'new'
end as change_to_c
from mytable;
这是一本书
示例输出:
id change change_to_a change_to_b change_to_c
-----------------------------------------------
1 9 changed removed (null)
2 50 removed (null) new
3 83 new (null) changed
4 20 (null) changed changed
5 25 changed removed changed
id change changed removed new
-----------------------------------------
1 9 a b (null)
2 50 (null) a c
3 83 c (null) a
4 20 bc (null) (null)
5 25 ac b (null)
这是另一种方法。这还会返回3个额外的列,但每种更改类型一个,并且这些值是“a”、“b”、“c”的串联:
这是一本书
示例输出:
id change change_to_a change_to_b change_to_c
-----------------------------------------------
1 9 changed removed (null)
2 50 removed (null) new
3 83 new (null) changed
4 20 (null) changed changed
5 25 changed removed changed
id change changed removed new
-----------------------------------------
1 9 a b (null)
2 50 (null) a c
3 83 c (null) a
4 20 bc (null) (null)
5 25 ac b (null)
非常感谢,它工作得很好。您是如何知道使用
&
的,每个都有3个,而>
有些则有2个或4个?试错?逻辑?一旦你有了它,这是有道理的,但要做到这一点很难……这是逻辑。正如你所知道的,对于b和a,数字乘以4,然后再乘以4,得到c的情况。现在除以四等于移动2个二进制数字[这是我(老)年纪的程序员都知道的]。AND运算符是提取某些位的一种方法。数字3对应于数字的较低2位,其值可以为0-3。这当然是逻辑,当你掌握二进制,掩蔽和移位时,它会帮助你很多。啊,好的,我明白了。年轻的程序员在这里,仍然有很多东西需要学习,尤其是在这个抽象的层次上。我以前听说过bit-wise操作,但到目前为止从未真正使用过。再次感谢,回答得很好!我没有让你的工作……:/Postgres不想对整数使用&
,我无法正确地将changed
转换为bin或找到dectobin
函数。。。这是一个遗憾,因为我真的很好奇你是如何解决这个问题的,而没有像trincot那样进行一点明智的转换。@user3746543。如果col
是整数,则可以将其转换为操作的bit()
类型。