I need something similar to these 2 SO questions, but using Informix SQL syntax.
My data coming in looks like this:
id codes
63592 PELL
58640 SUBL
58640 USBL
73571 PELL
73571 USBL
73571 SUBL
I want to see it come back like this:
id codes
63592 PELL
58640 SUBL, USBL
73571 PELL, USBL, SUBL
See also group_concat() in Informix.
I believe that the answer you need is a user-defined aggregate, similar to this one:
CREATE FUNCTION gc_init(dummy VARCHAR(255)) RETURNING LVARCHAR;
RETURN '';
END FUNCTION;
CREATE FUNCTION gc_iter(result LVARCHAR, value VARCHAR(255))
RETURNING LVARCHAR;
IF result = '' THEN
RETURN TRIM(value);
ELSE
RETURN result || ',' || TRIM(value);
END IF;
END FUNCTION;
CREATE FUNCTION gc_comb(partial1 LVARCHAR, partial2 LVARCHAR)
RETURNING LVARCHAR;
IF partial1 IS NULL OR partial1 = '' THEN
RETURN partial2;
ELIF partial2 IS NULL OR partial2 = '' THEN
RETURN partial1;
ELSE
RETURN partial1 || ',' || partial2;
END IF;
END FUNCTION;
CREATE FUNCTION gc_fini(final LVARCHAR) RETURNING LVARCHAR;
RETURN final;
END FUNCTION;
CREATE AGGREGATE group_concat
WITH (INIT = gc_init, ITER = gc_iter,
COMBINE = gc_comb, FINAL = gc_fini);
Given a table of elements (called elements) with a column called name containing (funnily enough) the element name, and another column called atomic_number, this query produces this result:
SELECT group_concat(name) FROM elements WHERE atomic_number < 10;
Hydrogen,Helium,Lithium,Beryllium,Boron,Carbon,Nitrogen,Oxygen,Fluorine
Applied to the question, you should obtain the answer you need from:
SELECT id, group_concat(codes)
FROM anonymous_table
GROUP BY id;
CREATE TEMP TABLE anonymous_table
(
id INTEGER NOT NULL,
codes CHAR(4) NOT NULL,
PRIMARY KEY (id, codes)
);
INSERT INTO anonymous_table VALUES(63592, 'PELL');
INSERT INTO anonymous_table VALUES(58640, 'SUBL');
INSERT INTO anonymous_table VALUES(58640, 'USBL');
INSERT INTO anonymous_table VALUES(73571, 'PELL');
INSERT INTO anonymous_table VALUES(73571, 'USBL');
INSERT INTO anonymous_table VALUES(73571, 'SUBL');
INSERT INTO anonymous_table VALUES(73572, 'USBL');
INSERT INTO anonymous_table VALUES(73572, 'PELL');
INSERT INTO anonymous_table VALUES(73572, 'SUBL');
SELECT id, group_concat(codes)
FROM anonymous_table
GROUP BY id
ORDER BY id;
The output from that is:
58640 SUBL,USBL
63592 PELL
73571 PELL,SUBL,USBL
73572 PELL,SUBL,USBL
The extra set of data was added to test whether insert sequence affected the result; it appears not to do so (the codes are in sorted order; I'm not sure whether there's a way to alter - reverse - that order).
Notes:
LVARCHAR(10240)
(for 10 KiB), for example.SQL -528: Maximum output rowsize (32767) exceeded
, which surprises me.If you need to remove the aggregate, you can use:
DROP AGGREGATE IF EXISTS group_concat;
DROP FUNCTION IF EXISTS gc_fini;
DROP FUNCTION IF EXISTS gc_init;
DROP FUNCTION IF EXISTS gc_iter;
DROP FUNCTION IF EXISTS gc_comb;