2016-07-19 75 views
0

我有一個表:按位計算和計數數之後

create_table "fingerprint" do |t| 
    t.bit "fp1", limit: 64 
    t.bit "fp2", limit: 64 
    t.bit "fp3", limit: 64 
    t.bit "fp4", limit: 64 
    t.bit "fp5", limit: 64 
end 

fp1 | fp2 | fp3 | fp4 | fp5 
--------------------------- 
001 | 010 | 011 | 100 | 101 

而5個元素

的陣列
fp = [5,4,3,2,1] 

我想和位表中的每個記錄與每個元素fp,然後計算5列以上的設置位總數。

例如:

(001 & 5) = 001 
(010 & 4) = 000 
(011 & 3) = 011 
(100 & 2) = 000 
(101 & 1) = 001 
Total number of set bits: 4 

我想我的循環表的每一行此過程。請幫助我一個有效的方式來做到這一點(表格有大約100k行)。

預先感謝您。

+0

什麼類型的列? – klin

+0

對不起,我忘記了這個信息。我已經更新了這個問題,列類型是「位(64)」 –

+0

你最好的方法取決於你希望它「有效」的時候有多嚴重。你是否願意創建一個plpgsql函數或者一個動態加載的c語言函數?此查詢每天,每小時或每分鐘運行多少次? – NovaDenizen

回答

0

類型bit(3)的示例。你可以很容易地適應bit(64)

create table the_table (fp1 bit(3), fp2 bit(3), fp3 bit(3), fp4 bit(3), fp5 bit(3)); 
insert into the_table values 
('001', '010', '011', '100', '101'), 
('101', '011', '111', '110', '101'); 

with the_array(arr) as (
    values (array[5,4,3,2,1]) 
), 
new_values as (
    select 
     fp1 & arr[1]::bit(3) n1, 
     fp2 & arr[2]::bit(3) n2, 
     fp3 & arr[3]::bit(3) n3, 
     fp4 & arr[4]::bit(3) n4, 
     fp5 & arr[5]::bit(3) n5 
    from the_table 
    cross join the_array 
) 
select 
    *, 
    length(
     translate(
      concat(n1::text, n2::text, n3::text, n4::text, n5::text), 
      '0', 
      '') 
    ) bit_set 
from new_values; 

n1 | n2 | n3 | n4 | n5 | bit_set 
-----+-----+-----+-----+-----+--------- 
001 | 000 | 011 | 000 | 001 |  4 
101 | 000 | 011 | 010 | 001 |  6 
(2 rows) 
+0

這對於new_values來說是不好用的;它將不必要地實現整個結果集。 –

+0

@JimNasby - 什麼是更好的選擇? – klin

+0

@klin:謝謝你的這個例子 –