If the maximum number of products per personid is known in advance (and small), you can write quite efficient SQL:
sel
databasename
,tablename
,max(case when rnk = 1 then ColumnName else '' end) as Col1
,max(case when rnk = 2 then ColumnName else '' end) as Col2
,max(case when rnk = 3 then ColumnName else '' end) as Col3
,max(case when rnk = 4 then ColumnName else '' end) as Col4
,max(case when rnk = 5 then ColumnName else '' end) as Col5
,max(case when rnk = 6 then ColumnName else '' end) as Col6
,max(case when rnk = 7 then ColumnName else '' end) as Col7
,max(case when rnk = 8 then ColumnName else '' end) as Col8
from
(
sel
databasename
,tablename
,columnName
,rank() over (partition by databasename, tablename
order by columnid) as rnk
from
dbc.columns
where databasename = 'dbc'
and tablename in ('dbcinfo','Tables')
) dt
group by 1,2
order by 1,2
;
Or returning a concatenated string:
sel
databasename
,tablename
,trim(max(case when rnk = 1 then ColumnName else '' end)) ||
trim(max(case when rnk = 2 then ',' || ColumnName else '' end)) ||
trim(max(case when rnk = 3 then ',' || ColumnName else '' end)) ||
trim(max(case when rnk = 4 then ',' || ColumnName else '' end)) ||
trim(max(case when rnk = 5 then ',' || ColumnName else '' end)) ||
trim(max(case when rnk = 6 then ',' || ColumnName else '' end)) ||
trim(max(case when rnk = 7 then ',' || ColumnName else '' end)) ||
trim(max(case when rnk = 8 then ',' || ColumnName else '' end)) as Columns
from
(
sel
databasename
,tablename
,columnName
,rank() over (partition by databasename, tablename
order by columnid) as rnk
from
dbc.columns
where databasename = 'dbc'
and tablename in ('dbcinfo','Tables')
) dt
group by 1,2
order by 1,2
;
In both cases there will be some data lost, if there are more than 8 rows per value.
You can return a marker indicating missing data:
...
trim(max(case when rnk = 8 then ',' || ColumnName else '' end)) ||
trim(max(case when rnk > 8 then ',...' else '' end)) as Columns
Or you can add a new row for each group of 8 rows:
sel
databasename
,tablename
,trim(((rnk / 8) * 8) + 1 (format '999')) || ' to ' ||
trim(((rnk / 8) + 1) * 8 (format '999')) as Columns
,max(case when rnk mod 8 = 0 then ColumnName else '' end) (title '')
,max(case when rnk mod 8 = 1 then ColumnName else '' end) (title '')
,max(case when rnk mod 8 = 2 then ColumnName else '' end) (title '')
,max(case when rnk mod 8 = 3 then ColumnName else '' end) (title '')
,max(case when rnk mod 8 = 4 then ColumnName else '' end) (title '')
,max(case when rnk mod 8 = 5 then ColumnName else '' end) (title '')
,max(case when rnk mod 8 = 6 then ColumnName else '' end) (title '')
,max(case when rnk mod 8 = 7 then ColumnName else '' end) (title '')
from
(
sel
databasename
,tablename
,columnName
,rank() over (partition by databasename, tablename
order by columnid) - 1 as rnk
from
dbc.columns
where databasename = 'dbc'
and tablename in ('dbcinfo','Tables')
) dt
group by 1,2,3
order by 1,2,3
;
Dieter