【问题标题】:Concat GROUP BY in Vertica SQLVertica SQL 中的 Concat GROUP BY
【发布时间】:2014-01-10 20:06:17
【问题描述】:

我需要获取一个逗号分隔的 id 列表作为一个混乱的第三方 api 的字段:s 这是我想要实现的简化版本。

| id | name |
|====|======|
| 01 | greg |
| 02 | paul |
| 03 | greg |
| 04 | greg |
| 05 | paul |

SELECT name, {some concentration function} AS ids
FROM table
GROUP BY name

返回

| name | ids        |
|======|============|
| greg | 01, 03, 04 |
| paul | 02, 05     |

我知道 MySQL 有 CONCAT_GROUP 函数,我希望在不安装更多函数的情况下解决这个问题,因为环境原因。也许我可以使用 OVER 语句来解决这个问题?

【问题讨论】:

  • 如果我没记错的话,Vertica 是 Postgres 的一个分支。所以也许string_aggarray_agg 在那里可用。
  • @a_horse_with_no_name 不幸的是,两者都不是。

标签: sql vertica


【解决方案1】:

您必须将 OVER()NVL() 一起使用(您必须为每个名称扩展 10 个以上的实例):

CREATE TABLE t1 (
  id int,
  name varchar(10)
);

INSERT INTO t1
SELECT 1 AS id, 'greg' AS name
UNION ALL
SELECT 2, 'paul'
UNION ALL
SELECT 3, 'greg'
UNION ALL
SELECT 4, 'greg'
UNION ALL
SELECT 5, 'paul';

COMMIT;

SELECT name,
    MAX(DECODE(row_number, 1, a.id)) ||
    NVL(MAX(DECODE(row_number, 2, ',' || a.id)), '') ||
    NVL(MAX(DECODE(row_number, 3, ',' || a.id)), '') ||
    NVL(MAX(DECODE(row_number, 4, ',' || a.id)), '') ||
    NVL(MAX(DECODE(row_number, 5, ',' || a.id)), '') ||
    NVL(MAX(DECODE(row_number, 6, ',' || a.id)), '') ||
    NVL(MAX(DECODE(row_number, 7, ',' || a.id)), '') ||
    NVL(MAX(DECODE(row_number, 8, ',' || a.id)), '') ||
    NVL(MAX(DECODE(row_number, 9, ',' || a.id)), '') ||
    NVL(MAX(DECODE(row_number, 10, ',' || a.id)), '') id
FROM
    (SELECT name, id, ROW_NUMBER() OVER(PARTITION BY name ORDER BY id) row_number FROM t1) a
GROUP BY a.name
ORDER BY a.name;

结果

 名称 | ID
------+-------
 格雷格 | 1,3,4
 保罗 | 2,5

【讨论】:

  • 这似乎是一个很好的现实世界解决方案。 @Gregology,您是否有可能需要它是任意长度的串联?
【解决方案2】:

查看 vertica 安装附带的 vertica 示例中的 Concatenate UDAF 那是mysql的等价物。你可以直接安装它。

更多/opt/vertica/sdk/examples/AggregateFunctions/Concatenate.cpp

-- Shell comppile
cd /opt/vertica/sdk/examples/AggregateFunctions/
g++ -D HAVE_LONG_INT_64 -I /opt/vertica/sdk/include -Wall -shared -Wno-unused-value \
-fPIC -o Concatenate.so Concatenate.cpp /opt/vertica/sdk/include/Vertica.cpp

-- Create LIBRARY
CREATE LIBRARY AggregateFunctionsConcatenate AS '/opt/vertica/sdk/examples/AggregateFunctions/Concatenate.so';
CREATE AGGREGATE FUNCTION agg_group_concat AS LANGUAGE 'C++' NAME 'ConcatenateFactory' LIBRARY AggregateFunctionsConcatenate;


in the Concatenate.cpp
replace : input_len*10
with : 65000

代码中有两个地方需要替换这个值。

65000 是您可以使用 varchar 获得的最大长度。并且由于 vertica 不会将所有 65000 用于小于 65000 字符的值,所以你没问题。

【讨论】:

  • Concatenate 不能使用分隔符,如:community.dev.hp.com/t5/Vertica-Forum/… 以及 Guillaume 的回答中所述,您必须改用 github.com/vertica/Vertica-Extension-Packages/tree/master/…,这是 UDF 的第三部分,能够这样做
  • @user1084563 这工作正常,只需执行rtrim(agg_group_concat(field || ', '),', ')。 rtrim 会在最后去掉分隔符,这种方法不需要解析函数。
  • @woot 有趣的解决方法,绝对没有意识到您可以像这样在函数调用中附加。您可能还想将其添加到我发布的 vertica 社区线程中,因为那里尚未提出。
  • @user1084563 Ok
【解决方案3】:

从长远来看,最简单的方法是使用官方 Vertica UDF 之一,该 UDF 位于 github https://github.com/vertica/Vertica-Extension-Packages/tree/master/strings_package,它提供了 group_concat 函数。安装过程可以在 README 中找到,甚至还提供了示例。

【讨论】:

    猜你喜欢
    • 2011-06-21
    • 2022-09-22
    • 2022-12-01
    • 2016-03-06
    • 2012-10-02
    • 1970-01-01
    • 1970-01-01
    • 2019-02-11
    • 1970-01-01
    相关资源
    最近更新 更多