CREATE OR REPLACE FUNCTION search_by_tags(tags varchar[])
RETURNS TABLE (id_course integer, name text, tag_ct integer) AS
$func$
SELECT id_course, c.name, ct.tag_ct
FROM (
SELECT tc.id_course, count(*)::int AS tag_ct
FROM unnest($1) x(tag)
JOIN tagcourse tc USING (tag)
GROUP BY 1 -- first aggregate ..
) AS ct
JOIN course c USING (id_course) -- .. then join
ORDER BY ct.tag_ct DESC -- more columns to break ties?
$func$ LANGUAGE sql;
用于unnest()
从您的输入数组生成一个表格,就像@Clodoaldo 已经演示的那样。
为此,您不需要 plpgsql。使用简单的 SQL 函数更简单。
我使用unnest($1)
(with positional parameter) 而不是unnest(tags)
,因为后者仅对 SQL 函数中的 PostgreSQL 9.2+ 有效(与 plpgsql 不同)。我在这里引用手册:
在较旧的数值方法中,使用语法引用参数$n
:$1
指第一个输入参数,$2
第二个输入参数,依此类推。无论是否使用名称声明了特定参数,这都将起作用。
count()
返回bigint
。您需要将其强制转换int
为匹配声明的返回类型或声明返回的列作为bigint
开头。
使用USING
(equi-joins):USING (tag)
而不是ON tc.tag = c.tag
.
首先聚合然后加入另一个表通常更快。减少所需的连接操作。根据评论中@Clodoaldo 的
问题,这里有一个SQL Fiddle来演示差异。
OTOH,如果您在加入后进行聚合,则不需要子查询。更短,但可能更慢:
SELECT c.id_course, c.name, count(*)::int AS tag_ct
FROM unnest($1) x(tag)
JOIN tagcourse tc USING (tag)
JOIN course c USING (id_course)
GROUP BY 1
ORDER BY 3 DESC; -- more columns to break ties?