[英]How do I group "or" in pl/sql
I have legacy sql query that selects bit masks (among other data), something like:我有选择位掩码(以及其他数据)的遗留 sql 查询,例如:
1
2
1
How do I group this output like:我如何将此输出分组为:
1 or 2 or 1
That should be 3
那应该是
3
In order to do bit-wise logic you have to do a "bit" of math.为了执行按位逻辑,您必须进行“一点”数学运算。 (Bad puns are free around here:-).
(坏双关语在这里是免费的:-)。
Oracle defines the BITAND function. Oracle 定义了 BITAND 函数。 To get a bitwise 'or' you can define your own function as:
要获得按位“或”,您可以将自己的函数定义为:
FUNCTION BITOR(n1 IN NUMBER, n2 IN NUMBER)
RETURN NUMBER
IS
BEGIN
RETURN n1 - BITAND(n1, n2) + n2;
END BITOR;
And for completeness, BITXOR is为了完整起见,BITXOR 是
FUNCTION BITXOR(n1 IN NUMBER, n2 IN NUMBER)
RETURN NUMBER
IS
BEGIN
RETURN BITOR(n1, n2) - BITAND(n1, n2);
END BITXOR;
Best of luck.祝你好运。
You can use the BITAND operator for AND operation.您可以使用 BITAND 运算符进行 AND 运算。 Using this you can build logic for writing a function for BITOR.
使用它,您可以构建用于为 BITOR 编写函数的逻辑。 Checkout this link http://www.oracledba.co.uk/tips/bitwise_ops.htm
查看此链接http://www.oracledba.co.uk/tips/bitwise_ops.htm
There are no aggregate bit operations in Oracle. Oracle 中没有聚合位操作。 One method is an explicit aggregation, bit by bit:
一种方法是逐位显式聚合:
select ((case when max(bitand(bits, 1)) > 0 then 1 else 0 end) +
(case when max(bitand(bits, 2)) > 0 then 2 else 0 end) +
(case when max(bitand(bits, 4)) > 0 then 4 else 0 end) +
(case when max(bitand(bits, 8)) > 0 then 8 else 0 end) +
(case when max(bitand(bits, 16)) > 0 then 16 else 0 end) +
(case when max(bitand(bits, 32)) > 0 then 32 else 0 end) +
(case when max(bitand(bits, 64)) > 0 then 64 else 0 end) +
(case when max(bitand(bits, 128)) > 0 then 128 else 0 end) +
)
If you wanted an aggregate bitwise AND, then you would use min()
instead of max()
.如果你想要一个聚合按位与,那么你会使用
min()
而不是max()
。
If I understand you correctly, you want an aggregate bit-or function.如果我理解正确的话,您需要一个聚合位或函数。 Oracle doesn't provide one, to my knowledge, so you have to roll your own using their ODCI (Oracle Data Cartridge Interface).
Oracle 没有提供,据我所知,因此您必须使用他们的 ODCI(Oracle 数据盒接口)自己推出。 Here's a working example:
这是一个工作示例:
CREATE OR REPLACE TYPE matt_bitor_aggregate_impl AS OBJECT
(
result NUMBER,
CONSTRUCTOR FUNCTION matt_bitor_aggregate_impl(SELF IN OUT NOCOPY matt_bitor_aggregate_impl ) RETURN SELF AS RESULT,
-- Called to initialize a new aggregation context
-- For analytic functions, the aggregation context of the *previous* window is passed in, so we only need to adjust as needed instead
-- of creating the new aggregation context from scratch
STATIC FUNCTION ODCIAggregateInitialize (sctx IN OUT matt_bitor_aggregate_impl) RETURN NUMBER,
-- Called when a new data point is added to an aggregation context
MEMBER FUNCTION ODCIAggregateIterate (self IN OUT matt_bitor_aggregate_impl, value IN NUMBER ) RETURN NUMBER,
-- Called to return the computed aggragate from an aggregation context
MEMBER FUNCTION ODCIAggregateTerminate (self IN matt_bitor_aggregate_impl, returnValue OUT NUMBER, flags IN NUMBER) RETURN NUMBER,
-- Called to merge to two aggregation contexts into one (e.g., merging results of parallel slaves)
MEMBER FUNCTION ODCIAggregateMerge (self IN OUT matt_bitor_aggregate_impl, ctx2 IN matt_bitor_aggregate_impl) RETURN NUMBER --,
);
/
CREATE OR REPLACE TYPE BODY matt_bitor_aggregate_impl IS
CONSTRUCTOR FUNCTION matt_bitor_aggregate_impl(SELF IN OUT NOCOPY matt_bitor_aggregate_impl ) RETURN SELF AS RESULT IS
BEGIN
SELF.result := null;
RETURN;
END;
STATIC FUNCTION ODCIAggregateInitialize (sctx IN OUT matt_bitor_aggregate_impl) RETURN NUMBER IS
BEGIN
sctx := matt_bitor_aggregate_impl ();
RETURN ODCIConst.Success;
END;
MEMBER FUNCTION ODCIAggregateIterate (self IN OUT matt_bitor_aggregate_impl, value IN NUMBER ) RETURN NUMBER IS
BEGIN
IF self.result IS NULL THEN
self.result := value;
ELSE
-- Logic for bitwise OR
-- see also: http://www.oracledba.co.uk/tips/bitwise_ops.htm
self.result := self.result - BITAND(self.result, value) + value;
END IF;
RETURN ODCIConst.Success;
END;
MEMBER FUNCTION ODCIAggregateTerminate (self IN matt_bitor_aggregate_impl, returnValue OUT NUMBER, flags IN NUMBER) RETURN NUMBER IS
BEGIN
returnValue := result;
RETURN ODCIConst.Success;
END;
MEMBER FUNCTION ODCIAggregateMerge (self IN OUT matt_bitor_aggregate_impl, ctx2 IN matt_bitor_aggregate_impl) RETURN NUMBER IS
BEGIN
-- Logic for bitwise OR
-- see also: http://www.oracledba.co.uk/tips/bitwise_ops.htm
self.result := self.result - BITAND(self.result, ctx2.result) + ctx2.result;
RETURN ODCIConst.Success;
END;
END;
/
-- Now that you have a TYPE to implement the logic, here is where you define the new aggregate function
CREATE OR REPLACE FUNCTION matt_bitor_aggregate ( input NUMBER) RETURN NUMBER
PARALLEL_ENABLE AGGREGATE USING matt_bitor_aggregate_impl;
/
-- Here's a simple test with your test data set...
with test_data as (
SELECT 1 a FROM dual UNION ALL
select 2 from dual union all
select 1 from dual
)
select matt_bitor_aggregate(a)
from test_data;
-- Here is a more complex test that also highlights the fact that you can use ODCI custom aggregates with window clauses.
with test_data as (
SELECT 1 a FROM dual UNION ALL
select 2 from dual union all
select 1 from dual union all
select 16 from dual union all
SELECT 18 from dual)
select a, matt_bitor_aggregate(a) over ( partition by null order by rownum rows between 1 preceding and 1 following ) from
test_data;
As of Oracle 20c, you can do bitwise aggregates using the following functions:从 Oracle 20c 开始,您可以使用以下函数进行按位聚合:
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.