2015-11-03 75 views
0

我试图通过一组预先定义的整数来获得查询循环:环流式SQL查询 - PostgreSQL的

我做了查询这个问题很简单。这是伪代码很明显!

my_id = 0 
WHILE my_id < 10 
    SELECT * from table where id = :my_id` 
    my_id += 1 
END 

我知道,这个查询我可以做这样的事情其中id < 10 ..但我执行实际的查询是大约60线长,不少窗口语句都指的是有问题的变量。

它的工作原理,并得到我想要的结果,当我有变量设置为一个单一的数字..我只需要能够重新运行查询10次与不同的变量,希望结束了一个单一的集的结果。

到目前为止,我有这样的:

CREATE OR REPLACE FUNCTION stay_prices (a_product_id int) RETURNS TABLE (
    pid int, 
    pp_price int 
) AS $$ 
DECLARE 
    nights int; 
    nights_arr INT[] := ARRAY[1,2,3,4]; 
    j int; 
BEGIN 
    j := 1; 
    FOREACH nights IN ARRAY nights_arr LOOP 

    -- query here.. 

    END LOOP; 
    RETURN; 
END; 
$$ LANGUAGE plpgsql; 

但我得到这个回:

ERROR: query has no destination for result data 
HINT: If you want to discard the results of a SELECT, use PERFORM instead. 

所以我需要让我的查询SELECT ... INTO返回表不知何故?或者还有什么我可以做的吗?

编辑:这是我在运行实际查询的例子:

\x auto 
\set nights 7 

WITH x AS (
    SELECT 
     product_id, night, 
     LAG(night, (:nights - 1)) OVER (
      PARTITION BY product_id 
      ORDER BY night 
     ) AS night_start, 
     SUM(price_pp_gbp) OVER (
      PARTITION BY product_id 
      ORDER BY night 
      ROWS BETWEEN (:nights - 1) PRECEDING 
      AND CURRENT ROW 
     ) AS pp_price, 
     MIN(spaces_available) OVER (
      PARTITION BY product_id 
      ORDER BY night 
      ROWS BETWEEN (:nights - 1) PRECEDING 
      AND CURRENT ROW 
     ) AS min_spaces_available, 
     MIN(period_date_from) OVER (
      PARTITION BY product_id 
      ORDER BY night 
      ROWS BETWEEN (:nights - 1) PRECEDING 
      AND CURRENT ROW 
     ) AS min_period_date_from, 
     MAX(period_date_to) OVER (
      PARTITION BY product_id 
      ORDER BY night 
      ROWS BETWEEN (:nights - 1) PRECEDING 
      AND CURRENT ROW 
     ) AS max_period_date_to 

    FROM products_nightlypriceperiod pnpp 
    WHERE 
     spaces_available >= 1 
     AND min_group_size <= 1 
     AND night >= '2016-01-01'::date 
     AND night <= '2017-01-01'::date 
) 
SELECT 
    product_id as pid, 
    CASE WHEN x.pp_price > 0 THEN x.pp_price::int ELSE null END as pp_price, 
    night_start as from_date, 
    night as to_date, 
    (night-night_start)+1 as duration, 
    min_spaces_available as spaces 
FROM x 
WHERE 
    night_start = night - (:nights - 1) 
    AND min_period_date_from = night_start 
    AND max_period_date_to = night; 

这将让我所有支持我的所有产品在2016年nights夜间时间段的价格期间沿和我可以填写的最大空间数量。

我希望能够运行此查询,以获得所有我的产品在2到30天之间的所有期间。

这很可能会产生一个包含数百万行的表格。计划是定期重新创建此表,以便快速查看特定日期的可用内容。 products_nightlypriceperiod表示产品可用性的夜晚 - 例如, Product X has 3 spaces left for Jan 1st 2016, and costs £100 for the night

+0

把数字列表放在(temp)表中,你不需要循环。 – joop

+1

或者使用一个具有所需数字的CTE:'用the_values(my_id)作为(值(1),(2),(3))...'并加入反对。或者,如果数字总是连续的,请使用'generate_series()' –

回答

2

为什么使用循环?你可以做这样的事情(使用你的第一个查询):

with params as (
     select generate_series(1, 10) as id 
    ) 
select t.* 
from params cross join 
    table t 
where t.id = params.id; 

可以修改params有你真正想要的值。然后,只需使用cross join并让数据库“执行循环”。

+0

没有看到..谢谢。将看看它 - 我有的sql语句在它有一个子查询 - 并且子查询和主查询都使用相同的变量。我将把一个编辑过的版本放入问题中,因为这会使事情复杂化。 –

+0

@GuyBowden。 。 。将'params'放入子查询中,然后向外传播值。 –

+0

这很好,直到您需要使用LAG或ROW语句中的参数。我将用示例查询编辑我的问题。 –