簡體   English   中英

PostgreSQL選擇逗號分隔值列的不同值(不包括子集)

[英]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, ','));

SQL小提琴

但是我無法抗拒:不要在關系數據庫中使用逗號分隔的字符串。 你有更好的方法。 它稱為“表”。

首先將字符串處理成字符集,然后將字符集與自身交叉連接,不包括兩邊字符集相同的行。

接下來,聚合並在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'}

sql小提琴中的示例

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM