在psql中循环使用TIMESTAMPS的ARRAY进行复杂的SELECT

时间:2017-07-02 23:54:21

标签: sql arrays postgresql loops

我正试图在几张桌子上获取大量功能,而且我的目前是pSQL容量。使用9.6.2。

我正在尝试以可变数量的日期时间收集所有这些功能。目前,我在一个时间戳上运行它,并且不得不一遍又一遍地调用它,这对我来说太慢了。

我想发送一个在FROM(... UNION ...)中使用的时间戳数组。

CREATE OR REPLACE FUNCTION features_at_times(timestamp[])
  RETURNS TABLE (
        str_street_id                      varchar,
        ....blahhh, blah, blah.......
        Zone                               integer,
        DateTime                           timestamp
    ) AS
$func$
DECLARE
  stamp timestamp[];
  stamps timestamp[]:= array[];
BEGIN
    RETURN QUERY
    FOREACH stamp SLICE 1 IN ARRAY $1
    LOOP
        SELECT
          str_stuff_id,
          .....blahhh, blah, blah....
          COALESCE(MAX(zone_id), 0) "Zone",
          MAX("DateTime") "DateTime"

        FROM (

          SELECT
            thingo.*,
            str_timezone,
            timestamp stamp AT TIME ZONE str_timezone "DateTime"
          FROM thingo
          JOIN destination ON pk_city = pk_destination
          WHERE pk_city = '8fzdd56-7a52-11df-a34f-6b84rw853d3d'
          AND thingo.pk_thingo_status = 2

          UNION

          SELECT
              alt_thingo.*,
              str_timezone,
              timestamp stamp AT TIME ZONE str_timezone "DateTime"
          FROM thingo
          JOIN thingo AS alt_thingo USING (str_stuff_id)
          JOIN destination ON thingo.pk_city = pk_destination
          WHERE thingo.pk_city = '8fzdd56-7a52-11df-a34f-6b84rw853d3d'
          AND thingo.pk_thingo_status = 2

      ) as base
      LEFT JOIN block_observation_by_bin
          ON thingo_observation_by_bin.thingo_id = pk_thingo_id
          AND thingo_observation_by_bin.bin_id = ((to_char("DateTime",'D')::int - 1) * 24 + to_char("DateTime", 'HH24')::int)
          AND thingo_observation_by_bin.market_id = 94
      LEFT JOIN block_observation
          ON thingo_observation.thingo_id = pk_thingo_id
          AND thingo_observation.market_id = 94

      WHERE base.pk_thingo = '027ecb54-51ec-41a6-a57e-666fddbbff35'
      GROUP BY str_stuff_id;

    END LOOP;
  END;
$func$ LANGUAGE plpgsql;

我需要n次同样的读数。我看到FOREACH是一个选项,但我一直得到的只是错误。我想将时间戳传递给内部的两个SELECTS。

另外,我是否必须使用函数在psql中使用FOREACH?

1 个答案:

答案 0 :(得分:1)

RETURN QUERY的参数必须是SQL语句,但FOREACH是PL / pgSQL而不是SQL。

此外,

timestamp stamp AT TIME ZONE str_timezone "DateTime"

是无效的SQL。我没有检查是否有其他错误。

要从一个PL / pgSQL函数中的多个表中返回行,您必须使用这样的游标循环:

DECLARE
   ats timestamp without time zone;
   arow record;
BEGIN
   /* loop through the timestamps in the argument array */
   FOREACH ats IN ARRAY $1 LOOP
      /* loop through the results of the first query */
      FOR arow IN
         SELECT ...
      LOOP
         RETURN NEXT ...;
      END LOOP;
      /* loop through the results of the second query */
      FOR arow IN
         SELECT ...
      LOOP
         RETURN NEXT ...;
      END LOOP;
      ...
   END LOOP;
END;