Total number of "1s" in a Postgres bitmask
Asked Answered
I

6

9

Is there a way to get the total number of 1's in a Postgres "bit string" type?

Indigoid answered 15/12, 2009 at 21:0 Comment(0)
C
3

If you need it to be really efficient, here's a discussion: Efficiently determining the number of bits set in the contents of, a VARBIT field

Chauvinism answered 16/12, 2009 at 15:36 Comment(2)
@YehudaKatz: the discussion in the link is interesting, but it's about "first bit set" and "last bit set", which does not answer the question at hand. How can this can be the right answer?Korwin
there is nbits_set function tooGloomy
M
10
# select length(replace(x::text, '0', '')) from ( values ('1010111101'::bit varying) ) as something(x);
 length
--------
      7
(1 row)

And approach without string conversion:

# select count(*) from ( select x, generate_series(1, length(x)) as i from ( values ('1010111101'::bit varying) ) as something(x) ) as q where substring(x, i, 1) = B'1';
 count
-------
     7
(1 row)
Monazite answered 15/12, 2009 at 22:58 Comment(1)
I like the string replace & length method. +1Shinbone
C
3

If you need it to be really efficient, here's a discussion: Efficiently determining the number of bits set in the contents of, a VARBIT field

Chauvinism answered 16/12, 2009 at 15:36 Comment(2)
@YehudaKatz: the discussion in the link is interesting, but it's about "first bit set" and "last bit set", which does not answer the question at hand. How can this can be the right answer?Korwin
there is nbits_set function tooGloomy
P
1

I know, this is already an old topic, but I found a cool answer here: https://mcmap.net/q/241945/-counting-the-number-of-occurrences-of-a-substring-within-a-string-in-postgresql

So adapted it would be:

=# select length(regexp_replace((B'1010111101')::text, '[^1]', '', 'g'));
 length
--------
      7
(1 row)
Planchette answered 4/1, 2017 at 21:56 Comment(0)
J
1

Based on the discussion here, the above mentioned thread Efficiently determining the number of bits set in the contents of, a VARBIT field, and the Bit Twiddling Hacks page, I published a PostgreSQL extension: pg_bitcount. If you install that extension (see instructions there), you can count the number of bits set in a bitstring using:

# Register the extension in PostgreSQL
create extension pg_bitcount;

# Use the pg_bitcount function
select public.pg_bitcount(127::bit(8));
select public.pg_bitcount(B'101010101');

I compared a number of different algorithms for performance and using a table lookup seems to be the fastest. They are all much faster than converting to text and replacing '0' with ''.

Jemie answered 30/3, 2018 at 14:38 Comment(0)
S
0

The one / first bit? Or the total number of bits flipped on? The former: bit mask (& 1) the bit. The latter: A nasty query, like:

SELECT (myBit & 1 + myBit >> 1 & 1 + myBit >> 2 & 1) AS bitCount FROM myBitTable;

I suppose, you could also cast to a string and count the 1's in PL/SQL.

Shinbone answered 15/12, 2009 at 21:5 Comment(2)
total number of bits flipped on. Casting to a strings seems epically non-performant. I suppose I could write a function to handle the series of bits (I don't know enough PL/SQL to know whether I can easily loop over bitsize and extract the result)Indigoid
Hmmm... it looks like bitmasks are already strings internally, so maybe that solution isn't as bad as it looks.Indigoid
H
0

You have a simple way using plpgsql here.

Hedgerow answered 15/12, 2009 at 21:6 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.