【问题标题】:Remove duplicate (combination of 2 columns) values in a row删除一行中的重复(2 列的组合)值
【发布时间】:2017-02-21 13:42:04
【问题描述】:

我需要删除连续出现的重复值。 喜欢:

C1 | C2 | C3 | C4 | C5 | C6
----------------------------
1  | 2  |  1 | 2  | 1  | 3
1  | 2  |  1 | 3  | 1  | 4
1  |NULL|  1 |NULL| 1  |NULL

查询的输出应该是:

C1 | C2 | C3 | C4 | C5 | C6
----------------------------
1  | 2  |  1 | 3  |NULL|NULL
1  | 2  |  1 | 3  | 1  | 4
1  |NULL|NULL|NULL|NULL|NULL

如您所见,两列的组合在一行中应该是唯一的。

在第 1 行:
1/2 的组合是重复的,因此将其删除并且 1/3 在 c5/c6 中被移动到 c3/c4

在第 2 行:
1/2 , 1/3, 1/4 的组合没有重复,所以结果没有变化

在第 3 行:
所有 3 种组合都相同,因为所有组合中都存在 1/NULL,因此 c3 到 c6 设置为 null。

提前致谢

【问题讨论】:

  • 你的问题不是很准确。你到底需要什么?您的示例可以以多种方式解释,并且您的描述自相矛盾。 “删除一行中存在的重复值”与“两列的组合应该在一行中是唯一的”不同。另外,哪些组合应该是唯一的?
  • 更新了问题!!
  • 所有列都来自同一个表吗?显示查询的 SQL
  • 是的,所有列都在同一个表中
  • 我不明白您的输出是什么,并且我没有看到该输出与“2 列的组合应该在一行中是唯一的”这句话之间的匹配。你真的应该添加更多细节。

标签: sql oracle vertica


【解决方案1】:

也许有一个更聪明的方法......但你可以将它们转换成对,不同的(在这种情况下是联合),然后转回。

with pairs as (
    select id, c1 as x, c2 as y from mytable
    union
    select id, c3, c4 from mytable
    union 
    select id, c5, c6 from mytable
)
select id, 
       max(decode(rn,1,x)) c1,
       max(decode(rn,1,y)) c2,
       max(decode(rn,2,x)) c3,
       max(decode(rn,2,y)) c4,
       max(decode(rn,3,x)) c5,
       max(decode(rn,3,y)) c6
from (
    select id, x, y, row_number() over (partition by id) rn
    from pairs
) as foo
group by id

【讨论】:

    【解决方案2】:

    这个可行 - 包含用于测试的数据,但可能需要一些时间才能理解

    提示:取消注释 --debug 行下的代码 sn-ps,复制脚本直到只有这些代码 sn-ps 并将这部分粘贴到 SQL 提示符中以测试中间结果。

    原理是获取行标识符来“记住”行;然后垂直旋转 - 不是 3 列到 1 列,而是 6 列到 3 对列;然后,使用 DISTINCT 进行重复数据删除;然后在去重中间行的行标识符中获取索引;然后使用该索引再次水平旋转。

    像这样:

    WITH
    input(c1,c2,c3,c4,c5,c6) AS (
              SELECT 1,        2,1,        2,1,        3
    UNION ALL SELECT 1,        2,1,        3,1,        4
    UNION ALL SELECT 1,NULL::INT,1,NULL::INT,1,NULL::INT
    )
    ,
    -- need rowid
    input_with_rowid AS (
    SELECT ROW_NUMBER() OVER() AS rowid, * FROM input
    )
    ,
    -- three groupy of 2 columns, so pivot using 3 indexes
    idx3(idx) AS (SELECT 1 UNION SELECT 2 UNION SELECT 3)
    ,
    -- pivot vertically, two columns at a time and de-dupe
    pivot_pair AS (
    SELECT DISTINCT
      rowid
    , CASE idx 
        WHEN 1 THEN c1
        WHEN 2 THEN c3
        WHEN 3 THEN c5
      END AS c1
    , 
      CASE idx 
        WHEN 1 THEN c2
        WHEN 2 THEN c4
        WHEN 3 THEN c6
      END AS c2
    FROM input_with_rowid CROSS JOIN idx3
    )
    -- debug
    -- SELECT * FROM pivot_pair ORDER BY rowid;
    ,
    -- add sequence per rowid
    pivot_pair_with_seq AS (
    SELECT
      rowid
    , ROW_NUMBER() OVER(PARTITION BY rowid) AS seq
    , c1
    , c2
    FROM pivot_pair
    )
    -- debug
    -- SELECT * FROM pivot_pair_with_seq;
    
    SELECT
      rowid
    , MAX(CASE seq WHEN 1 THEN c1 END) AS c1
    , MAX(CASE seq WHEN 1 THEN c2 END) AS c2
    , MAX(CASE seq WHEN 2 THEN c1 END) AS c3
    , MAX(CASE seq WHEN 2 THEN c2 END) AS c4
    , MAX(CASE seq WHEN 3 THEN c1 END) AS c5
    , MAX(CASE seq WHEN 3 THEN c2 END) AS c6
    FROM pivot_pair_with_seq
    GROUP BY rowid
    ORDER BY rowid
    ;
    
    rowid|c1|c2|c3|c4|c5|c6
        1| 1| 2| 1| 3|- |-
        2| 1| 2| 1| 3| 1| 4
        3| 1|- |- |- |- |-
    

    【讨论】:

      【解决方案3】:

      将 marcothesane 的想法与枢轴/非枢轴运算符结合使用。如果应该对更多输入列进行重复数据删除,则更易于维护。这保持了源数据(列对)的顺序——而 marcothesane 的解决方案可能会根据输入数据重新排序列对。它也比marcothesane的慢一点。它仅适用于 11R1 及更高版本。

      WITH
      input(c1,c2,c3,c4,c5,c6) AS (
                SELECT 1,        2,1,        2,1,        3 from dual
      UNION ALL SELECT 1,        2,1,        3,1,        4 from dual
      UNION ALL SELECT 1,NULL ,1,NULL ,1,NULL   from dual
      )
      ,
      -- need rowid
      input_with_rowid AS (
      SELECT ROW_NUMBER() OVER (order by 1) AS row_id, input.* FROM input
      ),
      unpivoted_pairs as
      (
        select row_id, tuple_idx, val1, val2, row_number() over (partition by row_id, val1, val2 order by tuple_idx) as keep_first
        from input_with_rowid
        UnPivot include nulls(
                (val1, val2)  --measure 
                      for tuple_idx in ((c1,c2) as 1,
                                        (c3,c4) as 2,
                                        (c5,c6) as 3)
                )
      )
      select row_id, 
             t1_val1 as c1,
             t1_val2 as c2,
             t2_val1 as c3,
             t2_val2 as c4,
             t3_val1 as c5,
             t3_val2 as c6
      from (
            select row_id,  
                   val1, val2, row_number() over (partition by row_id order by tuple_idx) as tuple_order
            from unpivoted_pairs
            where keep_first = 1
            )
      pivot (sum(val1) as val1, sum(val2) as val2
             for tuple_order in ('1' as t1, '2' as t2, '3' as t3)
             )
      

      【讨论】:

        猜你喜欢
        • 2022-07-22
        • 2019-08-08
        • 2021-06-24
        • 2019-08-31
        • 2013-01-23
        • 2016-04-26
        • 2017-01-23
        • 2021-09-08
        • 1970-01-01
        相关资源
        最近更新 更多