PostgreSQL 存储过程:如何枚举查询

Posted

技术标签:

【中文标题】PostgreSQL 存储过程:如何枚举查询【英文标题】:PostgreSQL stored procedure: how enumerate query 【发布时间】:2017-05-26 18:45:07 【问题描述】:

我正在尝试执行一个查询,其中我通过了“赛季”,结果它显示了与车手、积分、构造函数和排名中的位置相关的信息。

我想要的是这样的:

POS IN RANKING | DRIVER NAME | CONSTRUCTOR NAME | POINTS
---------------------------------------------------------
    1           "Hamilton"     MC Laren         360
    2           "Alonso"       Ferrari          290
   ...                 ...                   ....

我得到的问题是我无法枚举行。我认为“排名中的位置”应该是函数 row_number() 的结果,但由于某种原因,我无法使其工作。

这是我的存储函数:

CREATE TYPE ranking_t AS (
pos integer,
driver character varying(30),
constructor character varying(30),
points integer
);

CREATE OR REPLACE FUNCTION pra2.GetRankingOfPilots(sea pra2.season.name%type)
RETURNS ranking_t AS $$
DECLARE
    ranking_pilots ranking_t;
BEGIN
    SELECT  
      row_number() OVER (ORDER BY totalpuntos),
      driver.name driver, 
      constructor.name constructor,
      season.name season,
      CAST(sum(runs.points) AS int) TotalPuntos
    INTO ranking_pilots
    FROM 
      pra2.hired hired
    INNER JOIN pra2.constructor on  hired.name_constructor = pra2.constructor.name
    INNER JOIN pra2.driver on hired.num_driver = pra2.driver.num
    INNER JOIN pra2.runs on pra2.driver.num=pra2.runs.num_driver
    INNER JOIN pra2.race on pra2.runs.name_race=pra2.race.name AND pra2.runs.season_fk=pra2.race.season_fk AND pra2.runs.season_fk=pra2.race.season_fk
    INNER JOIN pra2.season on hired.name_season=pra2.season.name AND pra2.race.season_fk=pra2.season.name
    WHERE
        pra2.season.name=sea
    GROUP BY
        season,driver,constructor
    ORDER BY
        TotalPuntos Desc;

END; 
$$ 
LANGUAGE plpgsql;

如果有任何建议,我将不胜感激。

提前谢谢你!

【问题讨论】:

阿隆索已经不在法拉利车队,也不在迈凯轮车队的汉密尔顿:P,只是说。 I cannot make it work. 有什么问题?有什么错误吗? 是的,错误是我尝试枚举查询,顺便说一下我使用函数 row_number() 它会产生错误,因为它说字段 totalpuntos 不存在 【参考方案1】:

获取 wrapper 查询中的行号。

另外:将返回类型更改为SETOF ranking_t,删除变量并使用RETURN QUERY

CREATE OR REPLACE FUNCTION pra2.GetRankingOfPilots(sea pra2.season.name%type)
RETURNS SETOF ranking_t AS $$
BEGIN
    RETURN QUERY
    SELECT row_number() OVER (ORDER BY totalpuntos)::int, *
    FROM (
        SELECT  
            driver.name driver, 
            constructor.name constructor,
            season.name season,
            CAST(sum(runs.points) AS int) TotalPuntos
        FROM 
            pra2.hired hired
        INNER JOIN pra2.constructor on  hired.name_constructor = pra2.constructor.name
        INNER JOIN pra2.driver on hired.num_driver = pra2.driver.num
        INNER JOIN pra2.runs on pra2.driver.num=pra2.runs.num_driver
        INNER JOIN pra2.race on pra2.runs.name_race=pra2.race.name AND pra2.runs.season_fk=pra2.race.season_fk AND pra2.runs.season_fk=pra2.race.season_fk
        INNER JOIN pra2.season on hired.name_season=pra2.season.name AND pra2.race.season_fk=pra2.season.name
        WHERE
            pra2.season.name=sea
        GROUP BY
            season,driver,constructor
        ) s
    ORDER BY
        TotalPuntos Desc;
END; 
$$ 
LANGUAGE plpgsql;

【讨论】:

不工作。它说“执行到了函数的末尾,没有找到 RETURN” 您的原始查询有SELECT INTO,但您的存储过程有RETURNS ranking_t ,所以您没有RETURN,但这是一个不同的错误 好的,现在正在工作,但它只给了我一行,它应该显示更多:/【参考方案2】:

我猜问题是您使用的是别名而不是源代码。

你不能这样做

SELECT 
  row_number() OVER (ORDER BY totalpuntos),
  CAST(sum(runs.points) AS int) TotalPuntos

所以你创建一个子查询

SELECT row_number() OVER (ORDER BY totalpuntos)
FROM ( SELECT   CAST(sum(runs.points) AS int) TotalPuntos
       From YourQuery
     ) as Subquery

也许您可以使用该功能,但在 OVER 内不确定是否可行。

SELECT 
  row_number() OVER (ORDER BY CAST(sum(runs.points) AS int)),

编辑:要返回一个你这样做的表

CREATE OR REPLACE FUNCTION foo(a int)
RETURNS TABLE(b int, c int) AS $$
BEGIN
  RETURN QUERY SELECT i, i+1 FROM generate_series(1, a) g(i);
END;
$$ LANGUAGE plpgsql;

【讨论】:

以上是关于PostgreSQL 存储过程:如何枚举查询的主要内容,如果未能解决你的问题,请参考以下文章

为啥在 PostgreSQL 存储过程中查询没有“结果数据的目标”?

PostgreSQL存储过程-基于SQL的存储过程

PostgreSQL存储过程-基于SQL的存储过程

PostgreSQL存储过程

如何使用 JDBC 调用 PostgreSQL 存储过程

输出多列的PostgreSQL函数或存储过程?