We are trying to create a SQL query in Sybase where we can concatenate multiple rows into one selected row.
Layout:
| Type | Skill |
----------------
| A | 1
| A | 2
| B | 1
ETC
I want the output to be like: A (1,2)
We are trying to create a SQL query in Sybase where we can concatenate multiple rows into one selected row.
Layout:
| Type | Skill |
----------------
| A | 1
| A | 2
| B | 1
ETC
I want the output to be like: A (1,2)
If using ASE 16 you may be able to roll your own function to simulate the list() function; see my responses in this thread: Implementing group_concat() in ASE
Pay attention to Edison's response about KBA 2260479 ... a bug when using table variables inside a transaction.
----------- per the suggestion to copy pertinent info from sap.com link ...
Referring to an example @ Percona example (sorry, not going to replicate that link, too; the examples attached to this post show the results of matching the percona examples anyway)
To mimic MySQL's GROUP_CONCAT() function in ASE we need to understand some issues/limitations/observations:
ASE does not allow aggregate/UDFs (eg, passing a result set as an argument to a function)
ASE does not allow defining a UDF with a table variable as an input parameter
ASE does not allow the creation of a #temp table inside a UDF
ASE 16 SP02+ DOES allow the creation/use of table variables inside a UDF
ASE DOES allow the exec() construct inside a UDF
the GROUP_CONCAT() argument consists of columns/strings to be appended, an 'order by' clause, and an optional SEPARATOR (see examples at the percona.com link - above); it's not too hard to see that the columns/strings + 'order by' clause are components of a SELECT query
we can simulate passing of a data set to the UDF by instead passing a SQL/SELECT query that represents the desired dataset; this SQL/SELECT query can then be executed via the exec() construct to provide the UDF with the desired data set
The gist of our UDF design:
NOTE: Due to our use of a table variable the following requires ASE 16.0 SP02+
1 - the UDF's input parameter - @sql varchar(XXX) - represents a SQL/SELECT statement supplied by the calling process
1a- @sql must be a complete stand-alone query (ie, you should be able to run the query on its own in a separate ASE session)
1b - the select/projection list of @sql matches the column(s) of the table variable (see next bullet)
1c - @sql includes any necessary 'group/order by' clauses (ie, the UDF will not perform any sort operations)
2 - the UDF creates a table variable with a column defined to hold the results of the @sql query
2a - the column(s) of the table variable must match, datatype wise, with the select/projection list of the @sql query
3 - the UDF populates the table variable via the exec() construct:
4 - the UDF uses a cursor to loop through the records in the table variable
4a - cursor does not have a 'order by' clause => assume rows are ordered, upon insert to the table variable, based on @sql
Some specifics about this particular UDF:
1 - I've created the UDF in the sybsystemprocs database and named it:
1a - the 'sp_' prefix means the UDF can be executed from within any database
1b - the 'f_' string allows me to quickly/visually see that this is a function and not a system stored proc
2 - the UDF has been created with the assumption that the incoming SQL/SELECT query will have a select/projection list consisting of a single varchar(100) column
2a - the calling process will need to perform any necessary datatype casting (to char) and any concatenation of columns/strings
2b - the @sql input parameter has been defined as varchar(1000), and the @separator has been defined as varchar(10) with a default of a single comma (',')
2c - the owner of the UDF will need to revise the varchar() lengths based on what they expect to handle in their environment
3 - since the UDF cannot be sure TF:7703 (allow accumulating of data, by row, into a single @variable) is enabled, and the UDF does not perform any sorting, we'll use a cursor to step through the records in our table variable
4 - it's not apparent from the percona.com examples how MySQL's GROUP_CONCAT() function handles appending NULL's with non-NULL values (eg, is the NULL ignored? is the NULL converted to the empty string ''? is the NULL converted to the string 'NULL'?); net result is that the UDF owner/user may need to revisit the UDF and/or @sql design if they find NULL's are not being handled as desired
Hmmmm, can't attach files to stackoverflow posts? ok, so cut-n-paste it is ... yuck, not quite what the source looks like ...
++++++++++++++ sp_f_group_concat.sql
++++++++++++++ sp_f_group_concat.test1.sql
++++++++++++++ sp_f_group_concat.test2.sql
++++++++++++++
NOTE: For the example queries you'll notice that the @sql string passed to the sp_f_group_concat() function is basically a copy of the parent query plus an additional 'where' clause to allow limiting the query to just the rows that match the parent query's 'group by' clause (ie, the additional 'where' clause matches the column(s) in the 'group by' clause)
Which specific type of Sybase database is this? if ASE, then you either have to use a loop approach (e.g. Cursor), or use a somewhat exotic trick with the UPDATE statement using local variables (too much to describe here quickly, but details are in my book 'tips, tricks and recipes for sybase ase'