简体   繁体   English

如何在 pl/sql 中对“或”进行分组

[英]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 开始,您可以使用以下函数进行按位聚合:

  1. BIT_AND_AGG BIT_AND_AGG
  2. BIT_OR_AGG BIT_OR_AGG
  3. BIT_XOR_AGG BIT_XOR_AGG

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM