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

时间:2015-12-31 12:38:29

标签: sql oracle plsql

我有遗留的sql查询,它选择位掩码(以及其他数据),如:

1
2
1

如何将此输出分组为:

1 or 2 or 1 

那应该是3

5 个答案:

答案 0 :(得分:4)

为了做逐位逻辑,你必须做一点数学运算。 (坏双关语在这里是免费的: - )。

Oracle定义了BITAND函数。要获得按位'或',您可以将自己的函数定义为:

FUNCTION BITOR(n1 IN NUMBER, n2 IN NUMBER) 
  RETURN NUMBER
IS
BEGIN
  RETURN n1 - BITAND(n1, n2) + n2;
END BITOR;

为了完整,BITXOR是

FUNCTION BITXOR(n1 IN NUMBER, n2 IN NUMBER)
  RETURN NUMBER
IS
BEGIN
  RETURN BITOR(n1, n2) - BITAND(n1, n2);
END BITXOR;

祝你好运。

答案 1 :(得分:1)

您可以使用BITAND运算符进行AND运算。使用它可以构建用于为BITOR编写函数的逻辑。结帐此链接http://www.oracledba.co.uk/tips/bitwise_ops.htm

答案 2 :(得分:1)

Oracle中没有聚合位操作。一种方法是逐位显式聚合:

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) +
       ) 

如果您想要按位AND,那么您可以使用min()代替max()

答案 3 :(得分:1)

如果我理解正确,你需要一个聚合位或函数。据我所知,Oracle不提供一个,所以你必须使用他们的ODCI(Oracle数据盒式磁带接口)自行推出。这是一个有效的例子:

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;

答案 4 :(得分:0)

从Oracle 20c开始,您可以使用以下功能进行按位聚合:

  1. BIT_AND_AGG
  2. BIT_OR_AGG
  3. BIT_XOR_AGG