【问题标题】:How to add a new column to a set of Function records如何向一组函数记录添加新列
【发布时间】:2017-03-23 06:30:12
【问题描述】:

我正在创建一个函数,它从标题为“序列”的表中返回一组记录。作为该表的一部分,我还在分析另一个表(“Log_Alpha”)并将适当的信息插入到记录中。迄今为止,我所做的是覆盖现有列数据,然后在我对函数的选择调用中重命名该列(IE SELECT * FROM Production1(parameters) as tbl(xxx,xxx,xxx,NewColumnName Real,xxx,xxx ...)

这很好用,但是我需要保留原始数据,因此宁愿在记录中添加一个新列。但是我该怎么做呢,因为记录直接从“序列”表中获取它的列名。

我的代码显示 rc."seqLogsIn" 是正在捕获(平均每日 SED)数据的列。然后通过代码底部的 SELECT 查询从数据库调用它,其中列重命名为 "AvLogSED"

这里是完整的函数,但是你真的只需要关注 SELECT AVG("logSED") 部分。

为了澄清,我想在记录中创建一个新列(称为 AvLogSED,作为函数的一部分)并将数据注入该新列,而不是“盗用”seqLogsIn。我该怎么做?

我在 Windows 7 桌面 PC 上运行 PostgreSQL 9.2.9,由 Visual C++ build 1600 编译,64 位(本地服务器副本也在桌面上运行)。

-- Function: production1(timestamp without time zone, timestamp without time zone)    
-- DROP FUNCTION production1(timestamp without time zone, timestamp without time zone);

CREATE OR REPLACE FUNCTION production1(tme1 timestamp without time zone, tme2 timestamp without time zone)
  RETURNS SETOF record AS
$BODY$
DECLARE
  rc Record;
  tmeA timestamp without time zone;
  tmeB timestamp without time zone;
  AverageSED Real;

BEGIN

tmeA := tme1 + '1 day'::interval;
tmeB := tme2 + '1 day'::interval;

-- get average SED for all logs in time/date range
SELECT AVG("logSED")::Real
  FROM "Log_Alpha"
  WHERE "logTime" >= DATE_TRUNC('DAY', tme1) AND "logTime" < DATE_TRUNC('DAY', tme2 + '1 day'::interval) -- Calculate average for each day from 00:00 hours from first day thru to 23:59:59.99 for last day
  INTO averageSED;

  FOR rc IN 
    SELECT *, averageSED 
    FROM "Sequence"
    WHERE "Sequence"."seqMinute" = 150 AND "Sequence"."seqTime" >= tmeA AND "Sequence"."seqTime" <= tmeB
    ORDER BY "Sequence"."seqTime" 

  LOOP
    rc."seqTime" = rc."seqTime" - '1 day'::interval;

    -- Use a subquery to calculate the average SED for all logs for the day pertaining to this record date field
    SELECT AVG("logSED")::Real into rc."seqLogsIn" FROM "Log_Alpha" -- Replace column seqLogsIn data from sequence table with Daily Average SED data. The column title can be renamed in function (SELECT) call as required
      WHERE "Log_Alpha"."logTime" >= DATE_TRUNC('DAY', rc."seqTime") and "Log_Alpha"."logTime" < (DATE_TRUNC('DAY', rc."seqTime") + '1 day'::interval); -- Date truncated (always start at 00:00 hours of the day) to counter offset induced by mn variable

    RETURN NEXT rc;  
  END LOOP;
END
$BODY$
  LANGUAGE plpgsql STABLE
  COST 100
  ROWS 1000;
ALTER FUNCTION production1(timestamp without time zone, timestamp without time zone)
  OWNER TO postgres;

这是将相应列“重命名”为 AvLogSED 的 select 函数调用。

select * from production1('2016-02-27 00:00:00','2016-03-11 00:00:00') as tbl(seqTime timestamp without time zone,seqMinute integer,AvLogSED Real,seqLogVolIn Real,seqFinishedVol Real,seqChipTonnes Real,seqSawdustTonnes Real,seqBinSortVol Real,seqTraySortVol Real,seqFlitchSortVol Real,seqBinSortPieces Real,seqTraySortPieces Real,seqFlitchSortPieces Real,seqBinSortRejects Real,seqBinSortSlash Real,seqTraySortRejects Real,seqTraySortSlash Real,seqCanterCants Real,seqSecBandCants Real,seqSecBandRecycled Real,seqCS1Cants Real,seqCS3Cants Real,seqE1Pieces Real,seqE1ManualRejects Real,seqE1OperatorRejects Real,seqE1ThicknessRejects Real,seqE1NoSortRejects Real,seqE1VolumeIn Real,seqE1VolumeOut Real,seqE2Pieces Real,seqE2ManualRejects Real,seqE2OperatorRejects Real,seqE2ThicknessRejects Real,seqE2NoSortRejects Real,seqE2VolumeIn Real,seqE2VolumeOut Real,seqE1Bypass Real,seqE2Bypass Real,seqBSVolumeIn Real,seqPrimaryRuntime Real,seqBinLugSpeed Real,seqBinLugFill Real,seqTrayLugSpeed Real,seqTrayLugFill Real,seqCompressor1kWh Real,seqCompressor2kWh Real,seqCompressor3kWh Real,seqCompressor4kWh Real,seqKiln1and2GJ Real,seqKiln3GJ Real,seqKiln4GJ Real,seqKiln5GJ Real,seqKiln6GJ Real,seqKiln7GJ Real,seqKiln8GJ Real,seqKiln9GJ Real,seqKiln10GJ Real,seqKiln11GJ Real,seqKiln12GJ Real,seqFlitchTray10 Real,seqFlitchReturn Real,seqBSLiftOut Real,seqSecCantRuntime Real,seqSecBandRuntime Real,seqSecCS1Runtime Real,seqSecCS3Runtime Real,seqEdger1Runtime Real,seqEdger2Runtime Real,seqBinSorterRuntime Real,seqTraySorterRuntime Real,seqFlitchSorterRuntime Real,seqReEntryE1Minutes Real,seqReEntryChipMinutes Real,seqAwaitingLogs Real,seqBSUtilisation Real,seqTSUtilisation Real,seqFSUtilisation Real,seqDebarkerRuntime Real,seqReEntryChipCount Real,seqReEntryE1Count Real,Reserved2 Real,Reserved3 Real,Reserved4 Real,Reserved5 Real,Reserved6 Real,AverageSED Real)

【问题讨论】:

    标签: sql postgresql function record


    【解决方案1】:

    您可以像这样返回任意记录:

    RETURN NEXT ROW(val1, val2, ...);
    

    这样你就不受现有类型的限制。

    【讨论】:

    • 我试过了:[RETURN NEXT rc(seqTime timestamp without time zone,seqMinute integer,seqLogsIn Real,seqLogVolIn Real...); ] 但我收到一个错误返回,说明在“(”处或附近出现错误。也尝试使用和不使用数据类型。
    • 你应该返回rc(val1, val2, ...),这是一个语法错误,而是ROW(val1, val2, ...)ROW 是字面意思的关键字。
    【解决方案2】:

    发现解决方法如下:

    FOR rc IN
        SELECT *, AverageSED, avDailySED
        FROM "Sequence"
        WHERE "Sequence"."seqMinute" = mn AND "Sequence"."seqTime" >= tmeA AND "Sequence"."seqTime" <= tmeB
        ORDER BY "Sequence"."seqTime"
      LOOP
    

    通过将 AverageSED 和 avDailySED 添加到 SELECT,这些列会自动添加到 rc 记录中。我发现的一个钩子是我还必须明确地将数据推送到记录 rc 中的 avDailySED 中。我的意思是我现有的代码行:

    SELECT AVG("logSED")::Real into avDailySED FROM "Log_Alpha" -- Store average SED value in new column
    

    将导致空白 avDailySED 列。改成这个解决了这个问题:

    SELECT AVG("logSED")::Real into rc.avDailySED FROM "Log_Alpha" -- Store average SED value in new column
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2010-09-30
      • 1970-01-01
      • 1970-01-01
      • 2014-05-15
      • 2017-08-15
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多