鉴于以下内容:
CREATE TABLE filters (
id BIGINT NOT NULL
, name TEXT NOT NULL
, range NUMRANGE NOT NULL
, UNIQUE (id, name)
);
INSERT INTO filters (id,name,range) VALUES (99,'value1','[45,90]'::NUMRANGE);
INSERT INTO filters (id,name,range) VALUES (99,'value2','[15,50]'::NUMRANGE);
INSERT INTO filters (id,name,range) VALUES (23,'value1','[45,90]'::NUMRANGE);
CREATE TABLE data (
value1 NUMERIC
, value2 NUMERIC
);
编辑 - 添加了样本数据行
// filter.id = 99, neither value1 or value2 match this row
INSERT INTO data (value1,value2) VALUES (40.01, 11.12);
// filter.id = 99, only value2 matches this row
INSERT INTO data (value1,value2) VALUES (15.48, 20.14);
// filter.id = 99, only value1 matches this row
INSERT INTO data (value1,value2) VALUES (53.48, 70.14);
// filter.id = 99, both value1 and value2 match this row
INSERT INTO data (value1,value2) VALUES (64.12, 33.48);
过滤器表包含一系列按ID分组的过滤器。
我想将一组特定的过滤器(即filters.id = 99)应用于数据表,其中每行过滤器都会将filters.range应用于匹配filters.name的数据列。
最初,模式在过滤器和数据中包含1:1列重复,这样可以使用filters.col3 = data.col3或通过范围比较来完成连接。问题是我知道有超过1000个过滤器我想在过滤器表中跟踪并应用于数据表。
尝试了一些谷歌搜索,但不知道如何说出这类问题。我知道我可以用外部语言形成查询,但是如果可能的话我想在纯SQL / PostgreSQL中执行它。
答案 0 :(得分:1)
你需要动态SQL。
为您的表添加代理PK有几个原因,其中一个原因是同一组内过滤器的稳定排序顺序。另一个:总是添加PK。
CREATE TABLE filter (
filter_id serial PRIMARY KEY -- add surrogate PK
, filter_grp int NOT NULL
, name text NOT NULL
, range numrange NOT NULL
);
此功能 all :
CREATE OR REPLACE FUNCTION f_get_data(_filter_grp int)
RETURNS SETOF data AS
$func$
DECLARE
_where text;
_arr numrange[];
BEGIN
SELECT string_agg(name || ' <@ $1[' || rn || ']', ' AND ') -- AND?
,array_agg(range)
INTO _where, _arr
FROM (
SELECT name, range
,row_number() OVER (ORDER BY filter_id) AS rn
FROM filter
WHERE filter_grp = _filter_grp
ORDER BY filter_id
) sub;
-- RAISE NOTICE '%', 'SELECT * FROM data WHERE ' || _where;
RETURN QUERY EXECUTE 'SELECT * FROM data WHERE ' || _where
USING _arr;
END
$func$ LANGUAGE plpgsql;
呼叫:
SELECT * FROM f_get_data(99);
这构建并执行以下形式的查询:
SELECT * FROM data
WHERE value1 <@'[45,90]'::numrange
AND value2 <@'[15,50]'::numrange;
SELECT * FROM data
可以方便地与SETOF data
结合作为函数的返回类型。
在构建查询字符串时,避免将值转换为文本并返回。而是使用USING
子句提供值,并在$n
的查询中使用EXECUTE
占位符。
在这种特殊情况下,值的数量也是动态的。我们可以通过使用数组索引来回避子弹,这些索引自动对应于聚合数组中值的位置。