I have 2 tables - course that contains id and name of the courses and tagCourse that contains tags for each course.
course tagcourse
------------ ----------------
PK id_course PK tag
name PK, FK id_course
I'd like to write a function that searches courses by given array of tags and returns them ordered by quantity of matching tags. However I don't know how to write it correctly and in an efficient way. Please help me.
ie.
CREATE OR REPLACE FUNCTION searchByTags(tags varchar[])
RETURNS SETOF.....
RETURN QUERY SELECT * FROM course c INNER JOIN tagcourse tc ON c.id_course = tc.id_course
WHERE ??? ORDER BY ???
END....
Use
unnest()
to produce a table from your input array, like already demonstrated by @Clodoaldo.You don't need plpgsql for this. Simpler with a plain SQL function.
I use
unnest($1)
(with positional parameter) instead ofunnest(tags)
, since the later is only valid for PostgreSQL 9.2+ in SQL functions (unlike plpgsql). I quote the manual here:count()
returnsbigint
. You need to cast it toint
to match the declared return type or declare the the returned column asbigint
to begin with.Perfect occasion to simplify the syntax a bit with
USING
(equi-joins):USING (tag)
instead ofON tc.tag = c.tag
.It's regularly faster to first aggregate, then join to another table. Reduces the needed join operations.
As per question of @Clodoaldo in the comments, here is an SQL Fiddle to demonstrate the difference.
OTOH, if you aggregate after the join, you don't need a subquery. Shorter, but probably slower: