![](/img/trans.png)
[英]MySQL - select distinct values from a column where values are separated by comma
[英]PostgreSQL Select distinct values of comma separated values column excluding subsets
假设具有带有列栏的表foo带有逗号分隔的值(“ a,b”,“ a,b,c”,“ a,b,c,d”,“ d,e”)如何选择最大的组合以及排除该组合中包含的所有子集(最大的子集):
以上述数据集为例,结果应为:
('a,b,c,d','d,e')和前两个实体('a,b','a,b,c')被排除,因为它们是('a,b, c,d') 。
考虑到逗号分隔的字符串中的所有值均按字母顺序排序
我尝试了以下查询,但结果似乎与我需要的有点相去甚远:
select distinct a.bar from foo a inner join foo b
on a.bar like '%'|| b.bar||'%'
and a.bar != b.bar
您可以使用string_to_array()
将字符串拆分为一个数组。 使用包含运算符@>
您可以检查一个数组是否包含另一个。 (请参阅“ 9.18。数组函数和运算符” 。)
在NOT EXISTS
子句中使用它。 fi.ctid <> fo.ctid
可以确保比较的行对的物理地址不相等,因为与同一行相比,一行的数组当然会包含该数组。
SELECT fo.bar
FROM foo fo
WHERE NOT EXISTS (SELECT *
FROM foo fi
WHERE fi.ctid <> fo.ctid
AND string_to_array(fi.bar, ',') @> string_to_array(fo.bar, ','));
但是我无法抗拒:不要在关系数据库中使用逗号分隔的字符串。 你有更好的方法。 它称为“表”。
首先将字符串处理成字符集,然后将字符集与自身交叉连接,不包括两边字符集相同的行。
接下来,聚合并在HAVING
子句中使用BOOL_OR
过滤掉任何字符集,该字符集是任何其他字符集的子集
将样本表放在cte中,查询变为:
WITH foo(bar) AS (SELECT '("a,b" , "a,b,c" , "a,b,c,d" , "d,e")'::TEXT)
SELECT bar, string_to_array(elems[1], ',') not_subset
FROM foo
CROSS JOIN regexp_matches(bar, '[\w|,]+', 'g') elems
CROSS JOIN regexp_matches(bar, '[\w|,]+', 'g') elems2
WHERE elems2[1] != elems[1]
-- my regex also matches the ',' between sets which need to be ignored
-- alternatively, i have to refine the regex
AND elems2[1] != ','
AND elems[1] != ','
GROUP BY 1, 2
HAVING NOT BOOL_OR(string_to_array(elems[1], ',') <@ string_to_array(elems2[1], ','))
产生输出
bar not_subset
'("a,b" , "a,b,c" , "a,b,c,d" , "d,e")' {'d','e'}
'("a,b" , "a,b,c" , "a,b,c,d" , "d,e")' {'a','b','c','d'}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.