检查一行中多列值之间的等于?

时间:2017-11-30 05:23:55

标签: sql oracle teradata

快速提问

我有一张这样的表

COLUMN_1 COLUMN_2 COLUMN_3 COLUMN_4 COLUMN_5  SAME
X1       X1       X1       X1       X1        X1
X1       X2       X1       X1       X3        DIFFERENT
X1       NULL     X1       X1       NULL      X1
X1       NULL     X2       NULL     X3        DIFFERENT

基本上我想知道如果column_1和第5列之间的所有列都相同,那么得到一个带有值(第1行)的列。如果不是所有列都不同,那么得到一个不同的列(第2行)。这些行可以包含空值(第3行,第4行),但它们不会影响标志。

BTW,列类型为STRING。

我希望在teradata或oracle中这样做。

非常感谢

PS:Column_1不为null,它可以包含从x1到x5的值。 Column_2到Column_5可以为null。

4 个答案:

答案 0 :(得分:2)

根据您使用的实际数据,您可以暂时将数据作为行取消,从那里您的问题很容易解决。在这里,我假设您的表中有一个名为row_id的主键。

使用您的示例数据......

with your_table as(
   select 1 as row_id, 'X1' as c1, 'X1' as c2, 'X1' as c3, 'X1' as c4, 'X1' as c5 from dual union all
   select 2 as row_id, 'X1' as c1, 'X2' as c2, 'X1' as c3, 'X1' as c4, 'X3' as c5 from dual union all
   select 3 as row_id, 'X1' as c1, null as c2, 'X1' as c3, 'X1' as c4, null as c5 from dual union all
   select 4 as row_id, 'X1' as c1, null as c2, 'X2' as c3, null as c4, 'X3' as c5 from dual
)
select * 
  from your_table; 

ROW_ID   C1  C2  C3  C4  C5
------   --  --  --  --  --
1        X1  X1  X1  X1  X1
2        X1  X2  X1  X1  X3
3        X1      X1  X1   
4        X1      X2      X3

使用如下所示的unpivot运算符,会将所有非空列值转换为每个自己的记录。请注意输出中缺少空值的方式。

select * 
  from your_table unpivot(colval for colname in(c1, c2, c3, c4, c5));

row_id   colname  colval
------   -------  ------
1            C1       X1
1            C2       X1
1            C3       X1
1            C4       X1
1            C5       X1
2            C1       X1
2            C2       X2
2            C3       X1
2            C4       X1
2            C5       X3
3            C1       X1
3            C3       X1
3            C4       X1
4            C1       X1
4            C3       X2
4            C5       X3

......从这里可以轻松解决您的问题。

select row_id
      ,case when count(distinct colval) = 1 -- There is only one value across columns    
            then min(colval)                -- All are same, just pick one
            else 'DIFFERENT'
        end one_value
  from your_table unpivot (colval for colname in(c1, c2, c3, c4, c5))
 group -- Group by to reassemble the record 
    by row_id 

修改 在澄清了C1和可空性之后,问题就更加简单了:

select case when not c1 = all(c2,c3,c4,c5) then 'DIFFERENT' else c1 end
  from your_table;

但我总是留下旧答案,因为它解决了所有列都可以为空的问题。

答案 1 :(得分:1)

使用触发器可以这样:

CREATE OR REPLACE TRIGGER TRIGGER1 
BEFORE INSERT OR UPDATE ON TEST 
FOR EACH ROW
BEGIN
  IF :new.COLUMN1= :new.COLUMN2
     AND :new.COLUMN3=:new.COLUMN1
     AND  :new.COLUMN4=:new.COLUMN1
     AND :new.COLUMN5=:new.COLUMN1     

   THEN
    :new.same:='SAME';
    ELSE
    :new.same:='DIFFERENT';

    END IF;

END;

您可以考虑在上面的触发器中添加NULL条件检查。

答案 2 :(得分:0)

当第1列定义为NOT NULL时,您可以应用以下逻辑:连接第2列到第5列并删除第1列中字符串的任何出现。当结果为空字符串时,所有列都相等(或NULL )。

CASE 
   WHEN OReplace(  Coalesce(COLUMN_2,'')
                 ||Coalesce(COLUMN_3,'')
                 ||Coalesce(COLUMN_4,'')
                 ||Coalesce(COLUMN_5,'')
                 ,COLUMN_1
                 ,'') = ''
   THEN COLUMN_1
   ELSE 'different'
end

编辑:

Ups,这太复杂了。更简单:

CASE
   WHEN column_1 <> column_2
     OR column_1 <> column_3
     OR column_1 <> column_4
     OR column_1 <> column_5
   THEN 'different'
   ELSE column_1   
end

答案 3 :(得分:0)

您可以考虑在表格中添加虚拟列:

alter table your_table add same as(
   case when not column_1 = all(column_2, column_3, column_4, column_5) 
        then 'DIFFERENT' 
        else column_1 
    end
);