最も効率的な解決策は、おそらく直接 SQL 集計を実行することです。パーミッションは有限であるため、個々のパーミッションには一定の数 (N) があります。各権限を N 列に分解し、( を使用してMAX
) 集計し、次の後に権限を再構成できます。
p1 = sign(BitAnd(permissions, 2^0))
p2 = sign(BitAnd(permissions, 2^1))
...
P1 = MAX(p1)
P2 = MAX(P2)
...
Permissions = 2^0 * P1 + 2^1 * P2 + ... + 2^(N-1) * PN
しかし、それは面倒で、新しいアクセス許可を追加するときにクエリを書き直す必要があります。
SQL> select name,
2 power(2, 0) * MAX(sign(BitAnd(permissions, power(2, 0))))
3 + power(2, 1) * MAX(sign(BitAnd(permissions, power(2, 1))))
4 + power(2, 2) * MAX(sign(BitAnd(permissions, power(2, 2))))
5 + power(2, 3) * MAX(sign(BitAnd(permissions, power(2, 3))))
6 + power(2, 4) * MAX(sign(BitAnd(permissions, power(2, 4))))
7 + power(2, 5) * MAX(sign(BitAnd(permissions, power(2, 5))))
8 + power(2, 6) * MAX(sign(BitAnd(permissions, power(2, 6))))
9 + power(2, 7) * MAX(sign(BitAnd(permissions, power(2, 7))))
10 + power(2, 8) * MAX(sign(BitAnd(permissions, power(2, 8))))
11 permissions
12 from cats
13 group by name;
NAME PERMISSIONS
--------------- -----------
Carl 15
Steve 23
代わりに、独自のユーザー定義集計を作成することをお勧めします ( Tom Kyte によるこの投稿に触発され、9ir2 でテスト済み):
SQL> create or replace type bin_agg_type as object
2 (
3 total NUMBER,
4
5 static function
6 ODCIAggregateInitialize(sctx IN OUT bin_agg_type )
7 return number,
8
9 member function
10 ODCIAggregateIterate(self IN OUT bin_agg_type ,
11 value IN NUMBER)
12 return number,
13
14 member function
15 ODCIAggregateTerminate(self IN bin_agg_type ,
16 returnValue OUT NUMBER,
17 flags IN number)
18 return number,
19
20 member function
21 ODCIAggregateMerge(self IN OUT bin_agg_type,
22 ctx2 IN bin_agg_type)
23 return number
24 );
25 /
Type created.
SQL> create or replace type body bin_agg_type
2 is
3
4 static function ODCIAggregateInitialize(sctx IN OUT bin_agg_type )
5 return number
6 is
7 begin
8 sctx := bin_agg_type ( 0 );
9 return ODCIConst.Success;
10 end;
11
12 member function ODCIAggregateIterate(self IN OUT bin_agg_type ,
13 value IN NUMBER)
14 return number
15 is
16 begin
17 self.total := self.total + value - BitAND(self.total, value);
18 return ODCIConst.Success;
19 end;
20
21 member function ODCIAggregateTerminate(self IN bin_agg_type ,
22 returnValue OUT NUMBER,
23 flags IN number)
24 return number
25 is
26 begin
27 returnValue := total;
28 return ODCIConst.Success;
29 end;
30
31 member function ODCIAggregateMerge(self IN OUT bin_agg_type ,
32 ctx2 IN bin_agg_type )
33 return number
34 is
35 begin
36 self.total := self.total+ctx2.total - BitAND(self.total, ctx2.total);
37 return ODCIConst.Success;
38 end;
39
40
41 end;
42 /
Type body created.
SQL> CREATE or replace
2 FUNCTION BitOr_Agg(input NUMBER)
3 RETURN NUMBER
4 PARALLEL_ENABLE AGGREGATE USING bin_agg_type ;
5 /
Function created.
それを呼びましょう:
SQL> SELECT name, bitor_agg(permissions) from cats group by name;
NAME BITOR_AGG(PERMISSIONS)
--------------- ----------------------
Carl 15
Steve 23
どれが最速か知りたいです。