В вашем примере есть несколько проблем.
- Вы пытаетесь передать параметр в функцию, одновременно присоединяясь к его результату, что повлияет на то, что подается в функцию.на первом месте.Такой замкнутый круг никогда не может работать на принципале.
Сообщение об ошибке совершенно ясно об этом:
ERROR: invalid reference to FROM-clause entry for table "qw"
LINE 5: join similarity(qw.weighting) as sim on sim.user_id = questi...
^
HINT: There is an entry for table "qw", but it cannot be referenced from this part of the query.
Но есть еще:
- Вы не можете передать целые значения SET OF функции, которая принимает одно значение.
- Вы не можете определить функцию с помощью random () как
STABLE
. - Ваш синтаксис противоречив.Псевдоним для некоторых таблиц, но не для других.Начните с того, чтобы исправить это.Возможно, вы путаете себя.
- Вы смешиваете идентификаторы
weighting
и weightings
.Предположительно опечатки. - Не называйте IN-параметры, если вы все равно будете ссылаться на них с пометкой $ n .Это только создает возможные конфликты имен.Или используйте имена, которые не могут быть перепутаны, например, с префиксом, который выделяет их.
Я превратил вашу демонстрацию в нечто, что будет работать:
-- DROP SCHMEMA x CASCADE;
CREATE SCHEMA x
CREATE TABLE x.questions (id int PRIMARY KEY, user_id int NOT NULL);
INSERT INTO x.questions SELECT generate_series(1,11), (random()*20000)::int;
CREATE TABLE x.users (id int PRIMARY KEY);
INSERT INTO x.users SELECT generate_series(1, 200);
CREATE FUNCTION x.question_weighting()
RETURNS TABLE (question_id int, weighting int) AS
$BODY$
SELECT q.id, (random()*10)::int
FROM x.questions q;
$BODY$
LANGUAGE sql;
CREATE FUNCTION x.similarity(int)
RETURNS TABLE (user_id int, score int) AS
$BODY$
SELECT u.id, (random() * $1)::int
FROM x.users u;
$BODY$
LANGUAGE sql;
WITH qqw AS (
SELECT q.id, q.user_id, qw.weighting
FROM x.questions q
JOIN x.question_weighting() qw ON qw.question_id = q.id
-- WHERE ??
)
SELECT id, weighting
FROM qqw
JOIN (
SELECT *
FROM x.similarity((
SELECT weighting
FROM qqw
-- WHERE ??
LIMIT 1
))
) sim USING (user_id);
Может быть, это можетвсе будет упрощено на более низком уровне.