从集

时间:2016-06-14 05:29:58

标签: sql postgresql function

我在PostgreSQL中有一个表,其中包含以下信息:

ID | Value | Total
12 | 'foo' | 16
15 | 'loo' | 1
13 | 'too' | 11
67 | 'roo' | 7

我必须构建的查询将被赋予一个逗号分隔的单个ID或多个IDS。只需要返回Value。如果有多个ID,则仅返回具有最低总计的集合的结果。

这是我的开始,但它并不完全是我所追求的:

IF(position(',' in sample_id)>0) THEN
    RETURN QUERY SELECT value FROM table WHERE table.id = ANY(regexp_split_to_array(sample_id,','));
ELSE
    RETURN QUERY SELECT value FROM table WHERE table.id = sample_id;
END IF;

编辑:要明确我正在构建一个

的功能
CREATE OR REPLACE FUNCTION public.get_test_results(IN sample_id text)
    RETURNS TABLE(test_result text) AS
    $BODY$
    BEGIN
        IF(position(',' in sample_id)>0) THEN
            RETURN QUERY SELECT value FROM table WHERE table.id = ANY(regexp_split_to_array(sample_id,','));
        ELSE
            RETURN QUERY SELECT value FROM table WHERE table.id = sample_id;
        END IF;
    END;
    $BODY$

使用:

get_test_results("342949283940829308")

OR

get_test_results("67, 12")

此调用中的ID值与示例表无关。如果有多个ID传递给函数,结果应仅返回集合中ID的最低TOTAL值。

2 个答案:

答案 0 :(得分:1)

您可以在嵌套选择中获取min(table.total)

我不使用PostgreSQL,但如果你的例子有效,你应该写:

RETURN QUERY SELECT table.value FROM table WHERE table.id = ANY(regexp_split_to_array(sample_id,',')) and table.total in (
    SELECT min(tbl.total) FROM table tbl WHERE tbl.id = ANY(regexp_split_to_array(sample_id,','))
);

请注意,正如评论中所述,您不需要检查是否传递了一个或多个值,因为在两种情况下都可以分割您的参数。

答案 1 :(得分:1)

只需使用限制条款:

select value 
from the_table
where id = ANY(regexp_split_to_array(sample_id,',')::int[])
order by total 
limit 1;

请注意,您还需要将regexp_split_to_array的结果转换为整数数组(::int[]),否则您无法使用any()将其与整数列进行比较。

你也不需要PL / pgSQL。一个简单的SQL函数可以:

CREATE OR REPLACE FUNCTION public.get_test_results(IN sample_id text)
   RETURNS TABLE(test_result text) AS
$BODY$
  select value 
  from the_table
  where id = ANY(regexp_split_to_array(sample_id,',')::int[])
  order by total 
  limit 1;
$BODY$
language sql;

请注意,如果有多个行具有相同的最小值,则上述行只会返回一行。

如果您需要所有这些行,可以使用窗口函数:

select value
from (
  select value, dense_rank() over (order by total) as rnk
  from the_table
  where id = ANY(regexp_split_to_array(sample_id,',')::int[])
) t
where rnk = 1