Is it possible to perform a bitwise group function?
MySQL:
SELECT user_id, BIT_OR(permissions) as all_perms
FROM permissions
GROUP BY user_id
Bitwise operation in Group By
Your question just became very interesting.
Create this function(you may want to reconsider the name)
CREATE function f_test
(
@param bigint
)
returns @t table (value bigint)
AS
BEGIN
;WITH CTE AS
(
SELECT
@param % 2 value,
1 multiplier,
@param / 2 remain
UNION ALL
SELECT
remain % 2,
multiplier * 2,
remain / 2
FROM
CTE
WHERE
remain > 0
)
INSERT @t
SELECT multiplier
FROM CTE
WHERE value = 1
RETURN
END
Now you can run this script, I am using a table variable, replace it with your table:
DECLARE @t table(PermissionId int, BitMask bigint)
INSERT @t values(1,4),(2,7),(1,8),(1,5)
SELECT
t1.PermissionId,
SUM(distinct t2.Value) Total
FROM
@t t1
CROSS APPLY
f_test(t1.BitMask) t2
GROUP BY
t1.PermissionId
Result:
PermissionId Total
1 13
2 7
Performing a bitwise sum
If all of your test values are single bits as in your example (1, 2, 8) - simply use SUM(DISTINCT col)
in your query.
Hope that helps.
(For reference: http://msdn.microsoft.com/en-us/library/ms187810.aspx)
How to use bitwise operations to assign specific bits of a byte according to two other bytes? (bit blend according to a mask)
The standard bithack for this is "Merge bits from two values according to a mask" - I added your variable names for the inputs to the existing comments from Sean Anderson's collection of bithacks.
unsigned int a; // (ByteToAlter) value to merge in non-masked bits
unsigned int b; // (ValuesToAssign) value to merge in masked bits
unsigned int mask; // (BitsToAssign) 1 where bits from b should be selected; 0 where from a.
unsigned int r; // result of (a & ~mask) | (b & mask) goes here
r = a ^ ((a ^ b) & mask);
As the bithack comments note, the straight-forward way is (a & ~mask) | (b & mask)
- clear the bits you're not keeping in each input, then OR them together.
How a ^ ((a ^ b) & mask)
works:
bitdiff = a^b
is the bitwise difference between those inputs.
It has a 1
where they differ, and a 0
where they're the same. (By definition of XOR).
a ^ bitdiff
would flip every bit in a
that's different from b
. In fact, b == a ^ bitdiff
.
One way to show that's true is that XOR is associative, so a ^ (a^b)
= (a ^ a) ^ b
.
And x^x
= 0, just like x-x = 0
.0 ^ x = x
, so (a^a) ^ b
= 0 ^ b
= b
.
But if we mask the bitdiff to only set bits of a
to bits from b
at certain positions, we've achieved our goal: bitwise blend according to a mask. blend = a ^ (bitdiff & mask);
Special cases of the (a & ~mask) | (b & mask)
simple version
If your inputs are arranged so ValuesToAssign
only has any 1
bits at positions selected by the mask, you can optimize away the b & mask
part, leaving just (a & ~mask) | b
. (Eraklon's answer). Clear the unselected bits, then OR in the new values to set any bits that should be set.
A further special case is when ValuesToAssign == BitsToAssign
, i.e. the modification only ever sets bits, never clearing them. That's what OR does, so of course this case optimizes to a | b
, with no need to clear bits in a
before ORing.
Efficiency:
r = a ^ ((a ^ b) & mask);
is only 3 boolean operations,
vs. 4 for (a & ~mask) | (b & mask)
if all three inputs are runtime-variables. (One bitwise NOT, two AND, plus an OR).
If mask
is a constant, then constant-propagation into ~mask
makes it a constant, and most machines can do AND-immediate with at least an 8-bit AND mask. So you'd still only need 3 instruction: two ANDs (with inverse constants) and an OR.
Some machines (like x86 with BMI1) even have an andn
instruction that does x & ~y
, allowing the (a & ~mask) | (b & mask)
to be done with 3 instructions.
For latency, (a & ~mask) | (b & mask)
has more instruction-level parallelism. If mask
and ~mask
are ready ahead of a
and b
, there are only two parallel AND operations, and an OR, from a
and b
inputs being ready to the output being ready. On a normal superscalar machine (that can do two independent AND ops in the same cycle), that's only 2 cycle latency from inputs to outputs. (Again, assuming mask
is ready early, or that an instruction like andn
exists to do a & ~mask
in a single operation).
If the critical path goes through mask
(i.e. it's not ready early), and you don't have an instruction like andn
to do ~
and &
as one operation, the latency from mask
to result
is 3 operations, ~
, &
, and |
. (Assuming the b & mask
can run in parallel without slowing down any of those three).
Latencies for (a & ~mask) | (b & mask)
on a modern OoO exec machine.
(Not the same thing as throughput cost)
- a -> result: 2 cycles
- b -> result: 2 cycles
- mask -> result: 3 cycles (or 2 on some machines)
But the bit-difference way doesn't have any ILP; it's a chain of 3 operations. a^b
requires both of those inputs to be ready for the first step, then mask
needs to be ready for the & mask
step. The final a ^ ...
step is using inputs that were already needed earlier. So it's only 3 operations, but they're serial.
Latencies for a ^ ((a ^ b) & mask)
on a modern OoO exec machine.
- a -> result: 3 cycles
- b -> result: 3 cycles
- mask -> result: 2 cycles
Related Q&As:
Merge bit sequences a and b according to a mask - this is called a blend in SIMD programming. IDK if anyone else uses the "bit-blend" term I like to use for this operation, but IMO that clearly describes it. x86's AVX-512 extension has a 3-input boolean operation
vpternlog
with a truth-table from an 8-bit immediate, and thus can do it in a single instruction.Swapping bits at a given point between two bytes - The same bithack idea, but applying the masked bit-difference to both inputs to exchange bits at the mask positions.
https://catonmat.net/low-level-bit-hacks - starts gently with an intro to the operators (like
^
being bitwise XOR). Includes bithacks that use + and - (and the carry propagation effects of hitting a 1 or 0, likex & (x-1)
to clear the right-most set bit.)https://agner.org/optimize/ for more about tuning for modern CPUs.
How to perform bitwise operations arithmetic in MS-ACCESS
If you can run your query in in ANSI-92 Query Mode (e.g. by changing the Access UI Query Mode or by connecting to it using ADO classic or ADO.NET), use the BAND
operator.
The following code sample prints this to the Immediate window:
8 AND 7: -1
8 BAND 7: 0
The first case (AND) treats both numbers as True values, so True AND True
gives -1 (True). I think the BAND approach is what you're after.
Public Sub BitwiseAndQuery()
'the db engine treats numbers as booleans with AND '
Debug.Print "8 AND 7: "; _
CurrentDb.OpenRecordset("SELECT 8 AND 7")(0)
'ADO includes BAND for bitwise AND '
Dim rs As Object
Set rs = CreateObject("ADODB.Recordset")
rs.Open "SELECT (8 BAND 7)", CurrentProject.Connection
Debug.Print "8 BAND 7:"; rs(0)
rs.Close
Set rs = Nothing
End Sub
Related Topics
Trigger Insert Old Values- Values That Was Updated
SQL Server Stored Procedure Parameters
Split Varchar into Separate Columns in Oracle
How to Exclude Records with Certain Values in SQL Select
Sql: Last_Value() Returns Wrong Result (But First_Value() Works Fine)
Guid Primary /Foreign Key Dilemma SQL Server
How to Compute Tf/Idf with SQL (Bigquery)
How to Swap Column Values in SQL Server 2008
Combining Order by and Union in SQL Server
What Is Best Way to Get Last Indexof Character in SQL 2008
Asynchronous Triggers in SQL Server 2005/2008
Do Link Tables Need a Meaningless Primary Key Field
How to Fill Missing Dates by Groups in a Table in SQL
Similarity Function in Postgres with Pg_Trgm
How to Keep Only One Row of a Table, Removing Duplicate Rows