如何使用LISTAGG和Regexp_replace获得不同的值

时间:2018-08-25 18:32:26

标签: sql oracle plsql

以下是我的查询:

SELECT LISTAGG(product_name, chr(10)) WITHIN GROUP (ORDER BY product_name) "Product_Listing"
FROM products;

查询的输出是:

apple
orange
apple
mango
orange
banana
banana
apple

必需的输出是:

apple
orange
mango
banana

如何为此使用regexp_replace?任何其他功能/想法。

谢谢。

2 个答案:

答案 0 :(得分:3)

例如,不使用REGEXP_REPLACE就可以使用DISTINCT来实现:

SELECT LISTAGG(product_name, chr(10)) WITHIN GROUP (ORDER BY product_name) 
       "Product_Listing" 
FROM (SELECT DISTINCT product_name FROM products) s;

DBFiddle Demo

答案 1 :(得分:2)

如果您只想查找包含不同产品的一行,那么Lukasz的方法可以很好地工作。

如果您实际上想要任何其他摘要列,那么它可能不会做您想要的事情。您可以改用它:

SELECT LISTAGG(CASE WHEN seqnum = 1 THEN product_name END, chr(10))
           WITHIN GROUP (ORDER BY product_name) as Product_Listing
FROM (SELECT p.*,
             ROW_NUMBER() OVER (PARTITION BY product_name ORDER BY product_name) as seqnum
      FROM products p
     ) p;

我不建议在LISTAGG()之后的 之后删除重复项,仅是因为Oracle对结果施加了很短的限制。但您可以这样做:

SELECT REGEXP_REPLACE(LISTAGG(product_name END, chr(10)) WITHIN GROUP (ORDER BY product_name),
                      '([^\x10]+)(\x10\1)+',
                      '\1'
                     ) as Product_Listing
FROM products p;

这将删除相邻的重复项。由于ORDER BY,重复项是相邻的。因此,它应该可以工作。