SQL:通过删除表中的指定项来减少表

时间:2017-01-04 10:01:57

标签: sql vertica

我在vertica db中有以下表格:

+-------+-------+-------+
| Item1 | Item2 | Item3 |
+-------+-------+-------+
| A     | B     | S     |
| S     | C     | D     |
| E     | F     | S     |
+-------+-------+-------+

每行代表一次交易(例如在商店购物)。我正在寻找一种可扩展的方法来删除表中的所有S项,而不是减少表来获得这个:

+-------+-------+
| Item1 | Item2 |
+-------+-------+
| A     | B     |
| D     | C     |
| E     | F     |
+-------+-------+

新表中行的顺序并不重要。

附注:表格中的每一行都有S项,因此无需担心null条目。

跟进:如果我想同时删除n个项目,有什么比运行n个问题的SQL查询更快的方法呢?

一种可能的解决方案是将术语0000替换或添加到相关项目中。然后按字母数字排序每一行并删除第一列,但我想知道是否有更优雅的方式。

2 个答案:

答案 0 :(得分:1)

可能有多种方法可以做到这一点。我会先将S转换为NULL。然后COALESCE删除NULL,只留下两个值。然后我会使用LEASTGREATEST对这两个值进行排序,以便获得干净的输出。

注意COALESCE我只是颠倒了顺序,以便在所有情况下(假设每个元组只有一个S值)这两个项目将是不同的。

with s_filtered as (
    select nullif(Item1,'S') Item1,
           nullif(Item2,'S') Item2,
           nullif(Item3,'S') Item3
    from mytable
)
select distinct least(coalesce(Item1,Item2)) Item1,
       greatest(coalesce(Item3,Item2)) Item2
from s_filtered

我不确定在这种情况下我是否理解问题的可扩展部分。如果你的意思是你想拥有超过3个项目,那么......这种方法不会很好。你可以这样做(减去排序,你必须做预处理),但它可能是很多创意合并。

或者,您可以在过滤掉S类型后进行规范化并执行某种分析工作。这样可以更好地支持更多项目。

示例如果您有6个项目,其中一个S(请注意,您需要将内容与ID绑在一起):

with ordered_mytable as (
    select id, item, row_number() over (partition by id order by item) rn
    from mytable
    where item <> 'S'
)
select id, 
       max(decode(rn,1,item)) Item1,
       max(decode(rn,2,item)) Item2,
       max(decode(rn,3,item)) Item3,
       max(decode(rn,4,item)) Item4,
       max(decode(rn,5,item)) Item5
from ordered_mytable
group by id

答案 1 :(得分:0)

好的,我设法以一种时髦的方式解决。

  1. 使用||

  2. 从所有行创建字符串
  3. 删除您不想要的字符串部分

  4. 使用SPLIT_PART

  5. 拆分字符串

    以下是查询:

    SELECT 
        SPLIT_PART(replace, ';', 2) AS c1, 
        SPLIT_PART(replace, ';', 3) AS c2 
    FROM 
        (SELECT replace (  ';'|| item1 ||';'|| item2 ||';'|| item3  ,     ';S'    ,     '') 
         FROM my_table ) AS temp
    

    我认为这个查询的方式可以很容易地为更大的表生成(例如使用python),并且它不涉及创建临时表。