Reputation: 3758
I have a table of tags:
id | text
----------
1 | art
2 | sports
3 | history
4 | science
and a table of posts (temporary):
id | post | tags
-----------------------------
1 | 'random post 1' | 'art, 'history'
2 | 'random post 2' | 'science'
3 | 'random post 3' | 'art, science, history'
4 | 'random post 4' | 'sports, science'
I'd like to build a many-to-many relationship between these tags and posts and I'm trying to figure out the sql query I'd need to build the following table (posts_tags
)
id | post_id | tag_id
-----------------------------
1 | 1 | 1
2 | 1 | 3
3 | 2 | 4
4 | 3 | 1
...
From the documentation, I can see that we can split the posts.tags
table
regexp_split_to_table(posts.tags, E',') AS tags
but not sure how to make this work with the needed SQL command.
Upvotes: 0
Views: 61
Reputation: 32336
First you need to create the table posts_tags
:
CREATE TABLE posts_tags (
id serial PRIMARY KEY,
post_id integer REFERENCES posts,
tag_id integer REFERENCES tags
);
INSERT INTO posts_tags (post_id, tag_id)
SELECT p.id, t.id
FROM posts p, regexp_split_to_table(p.tags, ',') AS x(tag), tags t
WHERE btrim(x.tag) = t."text";
The regexp_split_to_table()
function uses a lateral join (sections 7.2.1.4 and .5) on table posts
so that it can access the field tags
. Effectively this works as a JOIN
: you get a row for each combination of id
with the tags in that same row. You then match the tags to the text
field in the tags
table such that you can SELECT
the id
of the tag.
Upvotes: 1
Reputation: 176074
You could first create posts_tags
table and populate it based on both tables:
CREATE TABLE posts_tags(ID SERIAL PRIMARY KEY,
post_id INT NOT NULL, -- define foreign keys
tag_id INT NOT NULL);
INSERT INTO posts_tags(post_id, tag_id)
SELECT c.id, t.id
FROM (SELECT *, TRIM(regexp_split_to_table(p.tags, E',')) AS tag
FROM posts p) AS c
JOIN tags t
ON t."text" = c.tag
SELECT *
FROM posts_tags;
Output:
╔═════╦══════════╦════════╗
║ id ║ post_id ║ tag_id ║
╠═════╬══════════╬════════╣
║ 1 ║ 1 ║ 1 ║
║ 2 ║ 1 ║ 3 ║
║ 3 ║ 2 ║ 4 ║
║ 4 ║ 3 ║ 1 ║
║ 5 ║ 3 ║ 4 ║
║ 6 ║ 3 ║ 3 ║
║ 7 ║ 4 ║ 2 ║
║ 8 ║ 4 ║ 4 ║
╚═════╩══════════╩════════╝
Upvotes: 0