2014-01-10 8 views
4

Мне нужно получить список идентификаторов, разделенных запятыми, как поле для грязной сторонней api: s Это упрощенная версия того, чего я пытаюсь достичь.Concat GROUP BY in Vertica SQL

| 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?

+1

Vertica - это вилка Postgres, если я не ошибаюсь. Так что, возможно, 'string_agg' или' array_agg' доступны там. –

+2

@a_horse_with_no_name К сожалению, нет. – Kermit

ответ

2

Самый простой в долгосрочной перспективе следует использовать один из официальных UDF Vertica, который можно найти на github, в https://github.com/vertica/Vertica-Extension-Packages/tree/master/strings_package, который предоставляет функцию group_concat. Процедура установки должна быть найдена в README, и примеры даже предоставляются.

9

Вы должны будете использовать 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; 

Результат

 name | id 
------+------- 
greg | 1,3,4 
paul | 2,5
+0

Это похоже на хорошее решение в реальном мире. @Gregology, есть ли шанс, что вам нужно, чтобы это была произвольная конкатенация длины? – kimbo305

4

Посмотрите на конкатенацию UDAF в примерах Vertica, которая поставляется с установкой Vertica , что эквивалентно 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 - максимальная длина, которую вы можете получить с помощью варчара. и поскольку vertica не использует все 65000 для значений меньше 65000 символов, вы в порядке.

+3

Concatenate не имеет возможности использовать разделитель, как указано в: https://community.dev.hp.com/t5/Vertica-Forum/Does-Vertica-have-an-equivalent-to-MySQL-s- GROUP-CONCAT-function/td-p/208697, а также в ответе Гийома, вы должны вместо этого использовать https://github.com/vertica/Vertica-Extension-Packages/tree/master/strings_package, который является частью UDF третьей части, что способен делать это – user1084563

+1

@ user1084563 Это прекрасно работает, просто сделайте 'rtrim (agg_group_concat (поле || ','), ',')'. Rtrim удалит разделитель в конце, и этот метод не требует аналитических функций. – woot

+0

@woot Интересное обходное решение, определенно не понимало, что вы можете добавить в вызов функции, как это. Вы также можете добавить это в поток сообщества Vertica, который я опубликовал, поскольку там не было предложено. – user1084563