Is it possible to perform a bitwise group function?

后端 未结 5 983
轻奢々
轻奢々 2020-12-09 10:02

I have a field in a table which contains bitwise flags. Let\'s say for the sake of example there are three flags: 4 => read, 2 => write, 1 => execute a

相关标签:
5条回答
  • 2020-12-09 10:25

    MySQL:

    SELECT user_id, BIT_OR(permissions) as all_perms
    FROM permissions
    GROUP BY user_id
    
    0 讨论(0)
  • 2020-12-09 10:26

    You would need to know the possible permission components (1, 2 and 4) apriori (thus harder to maintain), but this is pretty simple and would work:

    SELECT user_id,
           MAX(BITAND(permissions, 1)) +
           MAX(BITAND(permissions, 2)) +
           MAX(BITAND(permissions, 4)) all_perms
    FROM permissions
    GROUP BY user_id
    
    0 讨论(0)
  • 2020-12-09 10:31

    And you can do a bitwise or with...

    FUNCTION BITOR(x IN NUMBER, y IN NUMBER)
    RETURN NUMBER
    AS
    BEGIN
        RETURN x + y - BITAND(x,y);
    END;
    
    0 讨论(0)
  • 2020-12-09 10:38

    Ah, another one of those questions where I find the answer 5 minutes after asking... Accepted answer will go to the MySQL implementation though...

    Here's how to do it with Oracle, as I discovered on Radino's blog

    You create an object...

    CREATE OR REPLACE TYPE bitor_impl AS OBJECT
    (
      bitor NUMBER,
    
      STATIC FUNCTION ODCIAggregateInitialize(ctx IN OUT bitor_impl) RETURN NUMBER,
    
      MEMBER FUNCTION ODCIAggregateIterate(SELF  IN OUT bitor_impl,
                                           VALUE IN NUMBER) RETURN NUMBER,
    
      MEMBER FUNCTION ODCIAggregateMerge(SELF IN OUT bitor_impl,
                                         ctx2 IN bitor_impl) RETURN NUMBER,
    
      MEMBER FUNCTION ODCIAggregateTerminate(SELF        IN OUT bitor_impl,
                                             returnvalue OUT NUMBER,
                                             flags       IN NUMBER) RETURN NUMBER
    )
    /
    
    CREATE OR REPLACE TYPE BODY bitor_impl IS
      STATIC FUNCTION ODCIAggregateInitialize(ctx IN OUT bitor_impl) RETURN NUMBER IS
      BEGIN
        ctx := bitor_impl(0);
        RETURN ODCIConst.Success;
      END ODCIAggregateInitialize;
    
      MEMBER FUNCTION ODCIAggregateIterate(SELF  IN OUT bitor_impl,
                                           VALUE IN NUMBER) RETURN NUMBER IS
      BEGIN
        SELF.bitor := SELF.bitor + VALUE - bitand(SELF.bitor, VALUE);
        RETURN ODCIConst.Success;
      END ODCIAggregateIterate;
    
      MEMBER FUNCTION ODCIAggregateMerge(SELF IN OUT bitor_impl,
                                         ctx2 IN bitor_impl) RETURN NUMBER IS
      BEGIN
        SELF.bitor := SELF.bitor + ctx2.bitor - bitand(SELF.bitor, ctx2.bitor);
        RETURN ODCIConst.Success;
      END ODCIAggregateMerge;
    
      MEMBER FUNCTION ODCIAggregateTerminate(SELF        IN OUT bitor_impl,
                                             returnvalue OUT NUMBER,
                                             flags       IN NUMBER) RETURN NUMBER IS
      BEGIN
        returnvalue := SELF.bitor;
        RETURN ODCIConst.Success;
      END ODCIAggregateTerminate;
    END;
    /
    

    ...and then define your own aggregate function

    CREATE OR REPLACE FUNCTION bitoragg(x IN NUMBER) RETURN NUMBER
    PARALLEL_ENABLE
    AGGREGATE USING bitor_impl;
    /
    

    Usage:

    SELECT user_id, bitoragg(permissions) FROM perms GROUP BY user_id
    
    0 讨论(0)
  • 2020-12-09 10:44

    I'm interested to find all users who have a particular flag set (eg: write) on ANY record

    What's wrong with simply

    SELECT DISTINCT User_ID
    FROM Permissions
    WHERE permissions & 2 = 2
    
    0 讨论(0)
提交回复
热议问题