【问题标题】:Compare two comma separated columns in PostgreSQL比较 PostgreSQL 中的两个逗号分隔的列
【发布时间】:2019-03-19 10:07:45
【问题描述】:

我有两个表,其中一个列包含逗号分隔的数据。我需要比较这两列。逗号分隔的字段可以按任何顺序排列,但顺序无关紧要。

create table x_a (id1 integer, shared text);
create table x_b (id1 integer, shared text);

insert into x_a values 
  (1, 'A,B,C,D,E')
, (2, 'A,B,C,D,E');

insert into x_b values 
  (1, 'B,A,C,E,D')
, (2, 'B,A,C,E');

我使用了下面的查询,但它没有返回任何输出:

select a.id1,b.id1, a.shared, b.shared
from x_a a ,x_b b
where a.id1 = b.id1 
and regexp_split_to_array(LOWER(a.shared),',')
  = regexp_split_to_array(LOWER(b.shared),',')

我不能使用运算符&&,因为它会返回id=2,这是错误的,因为“共享”列不是精确的副本。

【问题讨论】:

  • 因为 regexp_split_to_array(LOWER(a.shared),',') != regexp_split_to_array(LOWER(b.shared),','),因为 abcde != bacedabcde != bace 分别。
  • 更改您的数据库/表设计。存储逗号分隔值违反了关系数据库的基本规则。

标签: sql arrays postgresql


【解决方案1】:

我不能使用运算符&&,因为它会返回错误的id=2 ...

但你可以像这样使用array operators @> and <@

SELECT id1, a.shared AS a_shared, b.shared AS b_shared
FROM   x_a a
JOIN   x_b b USING (id1)
WHERE  string_to_array(a.shared, ',') @> string_to_array(b.shared, ',')
AND    string_to_array(a.shared, ',') <@ string_to_array(b.shared, ',');

如果 A 包含 B,B 包含 A,则两者相等 - 忽略重复项。

您可能希望存储(排序的)数组以开始 - 或使用 1:n 关系规范化您的数据库设计。

如果您的元素是 integer 数字,请考虑额外的 intarray 模块以获得卓越的性能。见:

【讨论】:

    【解决方案2】:

    数组的= 取决于元素的顺序,因此在将元素转换为数组时需要对其进行排序。我认为最简单的方法是使用您自己的功能来做到这一点。

    create function string_to_array_sorted(p_input text)
      returns text[]
    as
    $$
      select array_agg(t.x order by t.x)
      from unnest(string_to_array(lower(p_input), ',')) as t(x);
    $$
    language sql
    immutable;
    

    请注意,如果您不需要正则表达式,string_to_array()regexp_split_to_array() 更有效。

    使用上述函数,您的查询可以写成:

    select a.id1,b.id1, a.shared, b.shared
    from x_a a 
      join x_b b on a.id1 = b.id1 
    where string_to_array_sorted(a.shared) = string_to_array_sorted(b.shared);
    

    请注意,我用“现代”(30 岁)显式 JOIN 运算符替换了古老、过时且脆弱的隐式连接。

    您可以创建一个索引来加快速度:

    create index on x_a (id1, string_to_array_sorted(shared));
    create index on x_b (id1, string_to_array_sorted(shared));
    

    【讨论】:

    • 谢谢,它成功了。但我的表中确实有大量数据,所以我宁愿避免函数调用
    • 您已经拥有一个函数调用 (regexp_split_to_array) - 但您必须以某种方式对元素进行排序。无论您是在函数中还是在“内联”中执行此操作都无关紧要。 language sql 的开销(尤其是在声明 immutable 时)与“内联”相同功能(您需要额外的 group by)语句相比几乎没有开销。该函数使您能够在这些值上创建索引。如果您真的有数百万行,这实际上可能比您在语句中“内联”的任何内容都快
    • 此函数以花括号形式返回输出。基本上它将字符串转换为数组。例如字符串“ A,B,D,C,E' 被转换为数组,我们得到的输出为“ {a,b,c,d,e}
    • @PreetiKaur:是的,它返回一个数组 - 与 regexp_split_to_array 返回的相同
    猜你喜欢
    • 2012-10-29
    • 2010-12-09
    • 2023-03-16
    • 1970-01-01
    • 2013-07-02
    • 2020-02-02
    • 1970-01-01
    • 2014-03-16
    • 1970-01-01
    相关资源
    最近更新 更多