如何在 postgresql 中使用多个 RETURN QUERY 限制结果集
Posted
技术标签:
【中文标题】如何在 postgresql 中使用多个 RETURN QUERY 限制结果集【英文标题】:How to limit result set with multiple RETURN QUERY in postgresql 【发布时间】:2015-03-30 15:02:37 【问题描述】:我有多个 RETURN QUERY
语句的函数。最后我只想得到N
随机记录。如果我在最后将LIMIT max_size
设置为每个RETURN QUERY
语句,我将得到max_size
* 计数RETURN QUERY
次。
我的函数的简短版本:
CREATE OR REPLACE FUNCTION android_getproposedsongs_test(
IN puserid character varying, max_size int)
RETURNS TABLE(sid uuid, method text) AS
$BODY$
DECLARE
songCount int;
BEGIN
RETURN QUERY
SELECT trackid as sid, lower('popular') as method
FROM ratingrecord
WHERE trackid NOT IN (
SELECT trackid FROM ratingrecord WHERE userid = puserid)
AND ratingrecord.rating > 0
GROUP BY trackid
HAVING SUM(rating) > 0
ORDER BY SUM(rating) DESC
LIMIT max_size;
CREATE TEMP TABLE recommended ON COMMIT DROP
AS
SELECT trackid, lower('recommended')
FROM ratingrecord finalRate
INNER JOIN
(
SELECT otherRate.userid AS otherUserId
, SUM(myRate.rating * otherRate.rating) as SumRating
FROM ratingrecord AS myRate
INNER JOIN ratingrecord AS otherRate
ON myRate.trackid = otherRate.trackid
WHERE myRate.userid = puserid AND myRate.userid != otherRate.userid
GROUP BY otherRate.userid
HAVING SUM(myRate.rating * otherRate.rating) > 0
) AS userRelations
ON finalRate.userid = userRelations.otherUserId
WHERE finalRate.trackid NOT IN (SELECT trackid FROM ratingrecord WHERE userid = puserid)
GROUP BY finalRate.trackid
HAVING SUM(finalRate.rating * userRelations.SumRating) > 0
ORDER BY SUM(finalRate.rating * userRelations.SumRating) DESC
LIMIT max_size;
RETURN QUERY SELECT * FROM recommended;
-- another RETURN QUERY statements
END;
$BODY$
LANGUAGE plpgsql VOLATILE;
我想在结果集中添加 ORDER BY random() LIMIT max_size
之类的东西,但不知道该放在哪里。
【问题讨论】:
【参考方案1】:或者您使用UNION ALL
组合纯SQL 中的所有子查询并在末尾添加一次ORDER BY random() LIMIT n
。
或者你必须自己记录在 plpgsql 中返回的行数,像这样:
CREATE OR REPLACE FUNCTION android_getproposedsongs_test(puserid varchar, max_size int)
RETURNS TABLE(sid uuid, method text) AS
$func$
DECLARE
song_count int; -- I'd rather not use spurious capitalisation
running_ct int := 0;
ct int;
BEGIN
RETURN QUERY SELECT ... LIMIT max_size; -- apply to each individual query!
GET DIAGNOSTICS ct = ROW_COUNT;
running_ct := running_ct + ct;
IF running_ct >= max_size THEN
RETURN;
END IF;
RETURN QUERY SELECT ... LIMIT max_size;
GET DIAGNOSTICS ct = ROW_COUNT;
running_ct := running_ct + ct;
IF running_ct >= max_size THEN
RETURN;
END IF;
-- another RETURN QUERY statements
END
$func$ LANGUAGE plpgsql VOLATILE;
相关:
PDO pgsql - Count the rows affected by pgsql function但是,这只会返回 first N
行,而不是随机选择。要实现,请无限制返回所有 行,并在下一步应用ORDER BY random() LIMIT n
:
SELECT *
FROM android_getproposedsongs_test('foo', 3)
ORDER BY random() LIMIT 123;
您必须知道,获取随机行的成本可能要高得多,因为必须首先确定所有(可能很多)候选者。返回前N
行可能会便宜很多。
【讨论】:
以上是关于如何在 postgresql 中使用多个 RETURN QUERY 限制结果集的主要内容,如果未能解决你的问题,请参考以下文章
如何在 postgresql 中使用多个 RETURN QUERY 限制结果集
如何在 postgresql 中使用不同的返回数据执行多个选择查询?