1

Assume there is the following table schema and data

create table tbl(
 id integer primary key,
 name text,
 pid integer
);
insert into tbl
values
 (1,'d',0),
 (2,'c',1),
 (3,'b',1),
 (4,'e',1),
 (5,'b',0),
 (6,'a',0);

It is a one-level depth hierarchy of parent and child items.

I need to aggregate children names into their parents like so

 id | name | children_names
----+------+------------
 6 | a |
 1 | d | c, e, b
 5 | b |

children names need to be sorted within each row and the entire result need to be sorted by name column alphabetically, but all b names must always go last.

In PostgreSQL I would do it with row_number() over() window function like this

with
t as (select * from tbl order by name),
t2 as (select * from t where name<>'b' union all select * from t where name='b'),
t3 as (select *, row_number() over() from t2)
select a.id, a.name, string_agg(b.name, ', ' order by b.row_number)
from t3 a left join t3 b on a.id=b.pid and a.id<>b.id
where a.pid=0
group by a.id, a.name, a.row_number
order by a.row_number

but I need this in Android Room which lacks window functions yet.

So how to get the same result without window functions used?

asked Feb 11, 2020 at 21:41

2 Answers 2

1

To sort group_concat() values, the original rows must come from an ordered subquery:

SELECT id,
 name,
 group_concat(cname) AS children_names
FROM (SELECT p.id,
 p.name,
 c.name AS cname
 FROM tbl AS p
 LEFT JOIN tbl AS c ON p.id = c.pid
 WHERE p.pid = 0
 ORDER BY c.name = 'b',
 c.name)
GROUP BY id
ORDER BY name = 'b',
 name;
answered Feb 12, 2020 at 10:05
1
  • This is the one I was looking for! Just the last order by should be changed to ORDER BY name='b', name and it works perfect. Thanks you! Commented Feb 12, 2020 at 10:49
0

SQLite have no STRING_AGG() function.

SELECT t1.id, t1.name, COALESCE(GROUP_CONCAT(t2.name), '') children_names
FROM tbl t1
LEFT JOIN tbl t2 ON t1.id = t2.pid
WHERE t1.pid = 0
GROUP BY t1.id, t1.name;

fiddle

GROUP_CONCAT() have no ORDER BY clause. No way to affect on the concatenated values order.

PS. Of course you may try to emulate ordered concatenation using recursive CTE with concatenating values one-by-one in the order which you need, but this CTE will be too complex and, I think, this makes no sense.

PPS. If you need to get ROW_NUMBER() without window function by some field/expression which is unique you may use this trick.

answered Feb 12, 2020 at 5:06
3
  • is there a way to make b values apear at the end of the list with this technique? Commented Feb 12, 2020 at 8:57
  • @yaugenka Yes. One more trick - absolutely unsupportable. Commented Feb 12, 2020 at 9:35
  • wow that's becoms too complicated. There is a simpler solution from CL below. Commented Feb 12, 2020 at 10:47

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.