【问题标题】:How to limit result set with multiple RETURN QUERY in postgresql如何在 postgresql 中使用多个 RETURN QUERY 限制结果集
【发布时间】: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 之类的东西,但不知道该放在哪里。

【问题讨论】:

    标签: sql postgresql sql-limit set-returning-functions


    【解决方案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;
    

    相关:

    但是,这只会返回 first N 行,而不是随机选择。要实现,请无限制返回所有 行,并在下一步应用ORDER BY random() LIMIT n

    SELECT *
    FROM   android_getproposedsongs_test('foo', 3)
    ORDER  BY random() LIMIT 123;
    

    您必须知道,获取随机行的成本可能要高得多,因为必须首先确定所有(可能很多)候选者。返回前N 行可能会便宜很多

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2018-05-16
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2010-10-19
      相关资源
      最近更新 更多