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

SQL: Reduce table by removing specified Items in a table

我在 vertica 数据库中有以下 table:

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

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

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

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

旁注:table 中的每一行都有项目 S,因此无需担心 null 个条目。

跟进:如果我想同时删除 n 项怎么办,有没有比 运行 问题的 SQL 查询 n 次更快的方法?

一个可能的解决方案是替换或添加到有问题的项目 0000。比按字母数字对每一行排序并删除第一列,但我想知道是否有更优雅的方法。

可能有多种方法可以做到这一点。我会先将 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. 使用 ||

  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),并且不涉及创建临时表。