SQLite Forum

display rows as columns
Login

display rows as columns

(1) By anonymous on 2022-04-01 19:41:38 [link] [source]

hi!
I have a table like this:

id   name
4    PRO7
4    ProSieben
5    RTL
6    kabel eins
6    KABEL1
7    RTL II
7    RTL2
8    ARTE
...

How can I display it this way:

id   name1       name2
4    PRO7        ProSieben
5    RTL
6    kabel eins  KABEL1
7    RTL II      RTL2
8    ARTE
...

There are not more than 2 names per id !

thanks
Peter

(2) By Gerry Snyder (GSnyder) on 2022-04-01 20:52:13 in reply to 1 [link] [source]

Look at GROUP BY and the GROUP_BY() function.

Gerry

(3) By anonymous on 2022-04-01 21:03:01 in reply to 2 [link] [source]

hm - sorry but I can't see how GROUP BY could help.

(5) By Gerry Snyder (GSnyder) on 2022-04-01 21:55:12 in reply to 3 [link] [source]

Sorry, I meant "GROUP_CONCAT()"

(4.1) By Keith Medcalf (kmedcalf) on 2022-04-01 21:46:17 edited from 4.0 in reply to 1 [link] [source]

last=-1
first=1
EXEC SQL SELECT id, name FROM t
WHILE (!END OF ROWS)
 FETCH INTO :id, :name
 if id != last
  last = id
  if first
    first=0
    print "id", "name1", "name2"
  else
    print
  end
  print id, name,
 else
  print name,
 end
LOOP
print

(6.1) By Keith Medcalf (kmedcalf) on 2022-04-01 22:06:56 edited from 6.0 in reply to 4.1 [link] [source]

Then, of course, you may have misstated your goal and instead of wanting to know how to "display" the data, you want to make a new table-form (which is, obviously, quite a different thing from "display"):

create table t
(
    id  integer not null,
    name text not null
);
insert into t values
    (4,'PRO7'),
    (4,'ProSieben'),
    (5,'RTL'),
    (6,'kabel eins'),
    (6,'KABEL1'),
    (7,'RTL II'),
    (7,'RTL2'),
    (8,'ARTE');
  select id,
         max(iif(cn == 1, name, NULL)) as name1,
         max(iif(cn == 2, name, NULL)) as name2
    from (
           select id,
                  row_number() over (partition by id) as cn,
                  name
             from t
         )
group by id;

(7) By anonymous on 2022-04-01 22:19:14 in reply to 6.1 [link] [source]

Beautiful. You beat me to it :D

It's called a PIVOT operation:

https://oracle-base.com/articles/11g/pivot-and-unpivot-operators-11gr1

For the record, since I typed it as well:

with
DataSet
as
(
    select 4 as id, 'PRO7' as name union all
    select 4 as id, 'ProSieben' as name union all
    select 5 as id, 'RTL' as name union all
    select 6 as id, 'kabel eins' as name union all
    select 6 as id, 'KABEL1' as name union all
    select 7 as id, 'RTL II' as name union all
    select 7 as id, 'RTL2' as name union all
    select 8 as id, 'ARTE' as name
),
ResultSet
as
(
    select  DataSet.*,
            row_number() over( partition by id order by name ) as rn
    from    DataSet
)
select      ResultSet.id,
            max( case when ResultSet.rn = 1 then ResultSet.name end ) as name1,
            max( case when ResultSet.rn = 2 then ResultSet.name end ) as name2
from        ResultSet
group by    ResultSet.id
order by    ResultSet.id;
4|PRO7|ProSieben
5|RTL|
6|KABEL1|kabel eins
7|RTL II|RTL2
8|ARTE|

(11) By midijohnny on 2022-05-10 22:29:32 in reply to 7 [link] [source]

This is a nice answer and works really well. I'm just trying to understand how it works.

The thing that is confusing me is the purpose of the 'max' function - I note that I can swap it out for a 'min' or 'group_concat' function - and everything continues to work.

So is the use of 'max' (or 'min', 'group_concat') just a way of fitting-in with the group-by ?

Thanks !

(12) By Keith Medcalf (kmedcalf) on 2022-05-10 23:48:12 in reply to 11 [link] [source]

You are using a group by, and each "group" contains one value for each column somewhere amongst the group, and null everywhere else. The aggregate ignores null values so will return only the one value (which is also the min and the max and group_concat and perhaps others (that is, aggregates that return one (or only) of the non-null values provided)).

(13.1) By midijohnny on 2022-05-15 12:22:04 edited from 13.0 in reply to 12 [source]

Thanks for the explanation; still seems like a bit of a trick, but works nicely enough.

I made a modified version for the sake of it - since we are already using a WINDOW function - we can make use of the lead function.

with
DataSet
as
(
    select 4 as id, 'PRO7' as name union all
    select 4 as id, 'ProSieben' as name union all
    select 5 as id, 'RTL' as name union all
    select 6 as id, 'kabel eins' as name union all
    select 6 as id, 'KABEL1' as name union all
    select 7 as id, 'RTL II' as name union all
    select 7 as id, 'RTL2' as name union all
    select 8 as id, 'ARTE' as name
),
ResultSet
AS
(
    SELECT DataSet.*,
        row_number() OVER w1 AS rn,
	lead(name,0) OVER w1 AS name1,
	lead(name,1) OVER w1 AS name2
    FROM DataSet
    WINDOW w1 AS ( PARTITION BY id ORDER BY name )
) SELECT id,name1,name2 FROM resultset WHERE rn=1

Output:

id	name1	name2
4	PRO7	ProSieben
5	RTL	
6	KABEL1	kabel eins
7	RTL II	RTL2
8	ARTE	

(8) By anonymous on 2022-04-02 21:34:24 in reply to 6.1 [link] [source]

Thanks, that works perfectly.

(10) By Vadim Goncharov (nuclight) on 2022-05-07 22:55:41 in reply to 4.1 [link] [source]

Do SQLite allows such syntax?

(9) By anonymous on 2022-04-02 21:35:56 in reply to 1 [link] [source]

Thanks to all for your input.