我试图从存储的函数返回数组,并在where子句中使用它的输出,用于查询。但它不是出于不明原因而工作。我真的没有线索。请帮忙。
使用以下功能。
CREATE OR REPLACE FUNCTION terep_cstm.testdays(
v_in_date date,
v_n integer)
RETURNS text[] AS
$BODY$
declare
listndays text = '';
arrndays text[];
BEGIN
for i in 0..v_n
loop
listndays = listndays||''||(v_in_date - i*interval '1 day')::date::text||',';
end loop;
listndays = trim(trailing ',' from listndays);
arrndays = string_to_array(listndays,',');
return arrndays;
END
$BODY$
LANGUAGE plpgsql VOLATILE;
使用存储的函数执行此查询。
select retl_code,price_2, attr_1,start_date,price,printedprice
from tessttable abc
where abc.attr_1 = '011' and abc.price_2 = '034' and abc.retl_code = '00068247'
and abc.start_date = ANY (select testdays('2017-05-31'::date,7)) --'2017-05-31'
--and abc.start_date = ANY (ARRAY['2017-05-31','2017-05-30','2017-05-29','2017-05-28','2017-05-27','2017-05-26','2017-05-25','2017-05-24'])
--and abc.start_date in ('2017-05-31','2017-05-30','2017-05-29','2017-05-28','2017-05-27','2017-05-26','2017-05-25','2017-05-24');
这对任何运算符都不起作用,错误消息
错误:运算符不存在:text = text [];
请让我知道我在哪里弄错了。 abc。 start_date数据类型是文本,它是平台配置的。不幸的是,我们没有自由转换此列数据类型,只能携带这个。
似乎与
一起使用and abc.start_date = ANY (testdays('2017-05-31'::date,7));
但是查询被绞死了很长时间。我也可以看到解释计划中的不同。
Query:
select retl_code,price_2, attr_1,start_date,price,printedprice
from tessttable abc
where abc.attr_1 = '011' and abc.price_2 = '034' and abc.retl_code = '00068247'
and abc.start_date in ('2017-05-31','2017-05-30','2017-05-29','2017-05-28','2017-05-27','2017-05-26','2017-05-25','2017-05-24');
Explain Plan:
"Index Scan using tessttable_comp_date on tessttable abc (cost=0.70..41.70 rows=1 width=43)"
" Index Cond: ((start_date = ANY ('{2017-05-31,2017-05-30,2017-05-29,2017-05-28,2017-05-27,2017-05-26,2017-05-25,2017-05-24}'::text[])) AND (prd_price_attr_1 = '011'::text) AND (price_2 = '034'::text) AND (retl_code = '00068247': (...)"
Query:
select retl_code,price_2, attr_1,start_date,price,printedprice
from tessttable abc
where abc.attr_1 = '011' and abc.price_2 = '034' and abc.retl_code = '00068247'
and abc.start_date = ANY (testdays('2017-05-31'::date,7)) ;
Explain Plan:
"Index Scan using tessttable_comp_date on tessttable abc (cost=0.70..10285844.48 rows=4 width=43)"
" Index Cond: ((prd_price_attr_1 = '011'::text) AND (price_2 = '034'::text) AND (retl_code = '00068247'::text))"
" Filter: (start_date = ANY (just_n_days('2017-05-31'::date, 7)))"
答案 0 :(得分:2)
摆脱选择,只需将函数用作表达式:
and abc.start_date = ANY ( testdays('2017-05-31'::date,7) )
如果将abc.start_date
定义为date
,则不应将日期值与字符串数组进行比较。使函数返回date[]
。
该函数也可以简化为简单的SQL函数,不需要PL / pgSQL:
CREATE OR REPLACE FUNCTION testdays(v_in_date date, v_n integer)
RETURNS date[] AS
$BODY$
select array_agg(x::date)
from generate_series(current_date, current_date + 6, interval '1' day) x;
$BODY$
LANGUAGE sql;
要坚持使用错误的日期文本值,只需更改汇总的内容
CREATE OR REPLACE FUNCTION testdays(v_in_date date, v_n integer)
RETURNS text[] AS
$BODY$
select array_agg(to_char(x, 'yyyy-mm-dd'))
from generate_series(current_date, current_date + 6, interval '1' day) x;
$BODY$
LANGUAGE sql;
请注意,我将返回类型更改为date[]
,以便您将日期与日期进行比较。
但是,我不明白为什么你首先需要一个功能:
and abc.start_date between date '2017-05-31' and date '2017-05-31' + 7
将实现完全相同的事情,并且在大多数情况下会更快。