I have two child tables with a one-to-many relationship
to the parent table. I want to join
them without extra duplication.
In the actual schema, there are more one-to-many relationship
s to this parent and to child tables. I'm sharing a simplified schema to make the root of the problem to be easy to be seen.
Any suggestion is highly appreciated.
CREATE TABLE computer (
id SERIAL PRIMARY KEY,
name TEXT
);
CREATE TABLE c_user (
id SERIAL PRIMARY KEY,
computer_id INT REFERENCES computer,
name TEXT
);
CREATE TABLE c_accessories (
id SERIAL PRIMARY KEY,
computer_id INT REFERENCES computer,
name TEXT
);
INSERT INTO computer (name) VALUES ('HP'), ('Toshiba'), ('Dell');
INSERT INTO c_user (computer_id, name) VALUES (1, 'John'), (1, 'Elton'), (1, 'David'), (2, 'Ali');
INSERT INTO c_accessories (computer_id, name) VALUES (1, 'mouse'), (1, 'keyboard'), (1, 'mouse'), (2, 'mouse'), (2, 'printer'), (2, 'monitor'), (3, 'speaker');
This is my query:
SELECT
c.id
,c.name
,jsonb_agg(c_user.name)
,jsonb_agg(c_accessories.name)
FROM
computer c
JOIN
c_user ON c_user.computer_id = c.id
JOIN
c_accessories ON c_accessories.computer_id = c.id
GROUP BY c.id
I'm getting this result:
1 "HP" ["John", "John", "John", "Elton", "Elton", "Elton", "David", "David", "David"] ["mouse", "keyboard", "mouse", "mouse", "keyboard", "mouse", "mouse", "keyboard", "mouse"]
2 "Toshiba" ["Ali", "Ali", ""Ali"] ["monitor", "printer", "mouse"]
I want to get this result (by preserving duplicates if exist in database). And also be able to filter computers by user and/or accessory:
1 "HP" ["John", "Elton", "David"] ["keyboard", "mouse", "mouse"]
2 "Toshiba" ["Ali"] ["monitor", "printer", "mouse"]
3 "Dell" Null ["speaker"]