简体   繁体   English

如何从 Postgres 函数以表格形式返回结果?

[英]How to return results as table from Postgres function?

I have function script that I converted from SQL Server to Postgres, now when I'm running the function I get an error我有从 SQL Server 转换为 Postgres 的函数脚本,现在当我运行该函数时出现错误

ERROR: structure of query does not match function result type错误:查询结构与函数结果类型不匹配

My function gets 3 parameters ( siteid bigint, datefrom timestamp, dateto timestamp ) and should return a table which I included in code.我的函数有 3 个参数( siteid bigint, datefrom timestamp, dateto timestamp )并且应该返回一个我包含在代码中的表。 I used "Return Query".我使用了“返回查询”。

I'm executing my function like this:我正在像这样执行我的功能:

getrtbactivesiteplaces(1475, '2016-02-01', '2016-08-01')

How I can get this result as a table from my function?我如何从我的函数中以表格的形式获得这个结果?

This is screenshot of my function这是我的功能截图

{
CREATE OR REPLACE FUNCTION "whis2011"."getrtbactivesiteplaces"(IN siteid int8, IN datefrom timestamp, IN dateto timestamp) RETURNS SETOF "varchar" 
AS $BODY$

DECLARE
siteid BIGINT;
datefrom timestamp without time zone;
dateto   timestamp without time zone;


BEGIN


-- SET NOCOUNT ON added to prevent extra result sets from
-- interfering with SELECT statements.

   /* SQLWays Notice: SET TRANSACTION ISOLATION LEVEL READ COMMITTED must be called before procedure call */
-- SET TRANSACTION ISOLATION LEVEL READ COMMITTED


    -- Insert statements for procedure here
 RETURN QUERY SELECT pl."Id",
       pl."RtbActiveSiteId",
       pl."AdPlaceId",
       pl."AdPosition",
       pl."Ctr",
       pl."State",
       pl."BidPrice",
       pl."MinBidFloor",
       pl."MinBidFloorCurrency",
       pl."AverageCpm",
       pl."AverageClickCost",
       coalesce(SUM(ss."BidsCount"),0) AS BidsCount,
       coalesce(SUM(ss."ShowsCount"),0) AS ShowsCount,
       coalesce(SUM(ss."RealShowsCount"),0) AS RealShowsCount,
       coalesce(SUM(ss."ClicksCount"),0) AS ClicksCount,
       coalesce(SUM(ss."ClickLayerClicksCount"),0) as ClickLayerClicksCount,
       coalesce(SUM(ss."ShowsCost"),0::money) AS ShowsCost,
       coalesce(SUM(ss."ClicksCost"),0::money) AS ClicksCost,
       coalesce(SUM(ss."BidsCost"),0::money) AS BidsCost,
       coalesce(SUM(ss."SliderMovesCount"),0) AS SliderMovesCount
   FROM "whis2011"."RtbActiveSitePlaces" pl
   LEFT OUTER JOIN "whis2011"."RtbActiveSitePlaceStatistics" ss ON ss."RtbActiveSitePlaceId" = pl."Id"
   WHERE ss."Date" >= datefrom AND ss."Date" < dateto AND pl."RtbActiveSiteId" = siteid
   GROUP BY pl."Id", pl."RtbActiveSiteId", pl."AdPlaceId", pl."AdPosition", pl."Ctr", pl."State", pl."BidPrice", 
   pl."MinBidFloor", pl."MinBidFloorCurrency", pl."AverageCpm", pl."AverageClickCost";
END;
$BODY$
LANGUAGE plpgsql
COST 100
CALLED ON NULL INPUT
SECURITY INVOKER
VOLATILE;

}

Your function's return type is setof varchar , but it should be something like:你的函数的返回类型是setof varchar ,但它应该是这样的:

RETURNS TABLE (Id              integer,
               RtbActiveSiteId integer,
               ... etc ...
              )

You have two problems with your code and I have two recommendations for improvements.您的代码有两个问题,我有两个改进建议。

First of all, instead of RETURNS SETOF varchar you should do RETURNS TABLE ... specifying all columns that the function returns.首先,您应该执行RETURNS TABLE ...指定函数返回的所有列,而不是RETURNS SETOF varchar Secondly, you have three function parameters, whose names you redeclare in the function block, masking out the parameter values.其次,您有三个函数参数,您在功能块中重新声明它们的名称,屏蔽了参数值。 This is why the function returns nothing because the parameter values are not used.这就是函数不返回任何内容的原因,因为未使用参数值。

Thirdly, I put all the sums in a sub-query, which reads easier and is probably more efficient too.第三,我把所有的总和放在一个子查询中,这样读起来更容易,也可能更有效。 Lastly, since the function body is a single SQL statement, you should make this a SQL function, which is more efficient than a PL/pgSQL language function.最后,由于函数体是单个 SQL 语句,您应该将其设为 SQL 函数,这比 PL/pgSQL 语言函数更高效。

See below.见下文。

CREATE OR REPLACE FUNCTION "whis2011"."getrtbactivesiteplaces"
    (IN siteid int8, IN datefrom timestamp, IN dateto timestamp)
RETURNS 
  
 
  
  
    SETOF "varchar" 
   TABLE (id int, RtbActiveSiteId int, ...) -- add all fields
AS $BODY$

  
 
  
  
    DECLARE siteid BIGINT; datefrom timestamp without time zone; dateto timestamp without time zone; 
   -- don't redeclare parameters!!!

  
 
  
  
    BEGIN 
   -- not needed for a SQL function
    -- Insert statements for procedure here
    
  
 
  
  
    RETURN QUERY 
   SELECT pl."Id", -- SQL function uses simple SELECT
        pl."RtbActiveSiteId",
        pl."AdPlaceId",
        pl."AdPosition",
        pl."Ctr",
        pl."State",
        pl."BidPrice",
        pl."MinBidFloor",
        pl."MinBidFloorCurrency",
        pl."AverageCpm",
        pl."AverageClickCost",
        ss.*
    FROM "whis2011"."RtbActiveSitePlaces" pl
    LEFT JOIN (
        SELECT "RtbActiveSitePlaceId" AS "Id"
               coalesce(SUM("BidsCount"),0) AS BidsCount,
               coalesce(SUM("ShowsCount"),0) AS ShowsCount,
               coalesce(SUM("RealShowsCount"),0) AS RealShowsCount,
               coalesce(SUM("ClicksCount"),0) AS ClicksCount,
               coalesce(SUM("ClickLayerClicksCount"),0) as ClickLayerClicksCount,
               coalesce(SUM("ShowsCost"),0::money) AS ShowsCost,
               coalesce(SUM("ClicksCost"),0::money) AS ClicksCost,
               coalesce(SUM("BidsCost"),0::money) AS BidsCost,
               coalesce(SUM("SliderMovesCount"),0) AS SliderMovesCount
         FROM "whis2011"."RtbActiveSitePlaceStatistics"
         WHERE "Date" >= datefrom AND "Date" < dateto
         GROUP BY "RtbActiveSitePlaceId") ss USING ("Id")
    WHERE pl."RtbActiveSiteId" = siteid;

  
 
  
  
    END; 
    -- not needed for a SQL function
$BODY$ LANGUAGE sql STRICT STABLE; -- don't call on NULL input and use STABLE

You then call this function like so:然后像这样调用这个函数:

SELECT * FROM getrtbactivesiteplaces(1475, '2016-02-01', '2016-08-01');

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM