PLPGSQL 函数:在 ORDER BY 中使用输入参数
PLPGSQL Function: Use Input Parameter in ORDER BY
我正在尝试在 plpgsql 函数中定义条件 ORDER BY。
像这样:
CREATE OR REPLACE FUNCTION test_function(p_sort_order TEXT, p_limit INTEGER)
RETURNS TABLE (
id TEXT,
test TEXT
)
AS $$
BEGIN
RETURN QUERY SELECT
t.field1 AS id,
MIN(t.field2) AS test
FROM table t
GROUP BY t.field1
ORDER BY
CASE p_sort_order
WHEN ‘asc’ THEN test END ASC,
WHEN ‘desc’ THEN test END DESC
END
LIMIT p_limit;
END; $$
LANGUAGE 'plpgsql';
这些参数似乎只在 WHERE、LIMIT 等子句中有效,但在 ORDER BY 中无效(尽管我还没有找到任何官方文档)。
实现此目的的解决方法是什么?
根据 link,将您的 select
更改为:
ORDER BY
CASE WHEN p_sort_order = 'asc' THEN min(t.field2) END ASC,
CASE WHEN p_sort_order = 'desc' THEN min(t.field2) END DESC
LIMIT p_limit;
这里的神奇之处在于,case
个实例 return 要么是 test
要么是 null
,后面跟着的是 asc
或 desc
。如果 p_sort_order
是 desc
,那么你会得到:
ORDER BY
NULL ASC,
test DESC
NULL ASC
使所有行在排序规则中相等,因此 order by
落入 test DESC
项。
这对我适用于 PG10(根据您的评论更新):
create or replace function do_sort(p_sort_order text)
returns table (id int, name text)
as $$
begin
return query select users.id, min(users.email)
from users
group by users.id
order by case when p_sort_order = 'asc' then min(users.email) end asc,
case when p_sort_order = 'desc' then min(users.email) end desc
limit 10;
end; $$ language plpgsql;
CREATE FUNCTION
Time: 10.849 ms
select * from do_sort('desc');
┌───────┬───────────────────────┐
│ id │ name │
├───────┼───────────────────────┤
│ 9 │ 9user@example.com │
│ 99 │ 99user@example.com │
│ 999 │ 999user@example.com │
│ 9999 │ 9999user@example.com │
│ 99999 │ 99999user@example.com │
│ 99998 │ 99998user@example.com │
│ 99997 │ 99997user@example.com │
│ 99996 │ 99996user@example.com │
│ 99995 │ 99995user@example.com │
│ 99994 │ 99994user@example.com │
└───────┴───────────────────────┘
(10 rows)
Time: 87.236 ms
select * from do_sort('asc');
┌────────┬────────────────────────┐
│ id │ name │
├────────┼────────────────────────┤
│ 100000 │ 100000user@example.com │
│ 100001 │ 100001user@example.com │
│ 100002 │ 100002user@example.com │
│ 100003 │ 100003user@example.com │
│ 100004 │ 100004user@example.com │
│ 10000 │ 10000user@example.com │
│ 10001 │ 10001user@example.com │
│ 10002 │ 10002user@example.com │
│ 10003 │ 10003user@example.com │
│ 10004 │ 10004user@example.com │
└────────┴────────────────────────┘
(10 rows)
Time: 85.219 ms
我正在尝试在 plpgsql 函数中定义条件 ORDER BY。 像这样:
CREATE OR REPLACE FUNCTION test_function(p_sort_order TEXT, p_limit INTEGER)
RETURNS TABLE (
id TEXT,
test TEXT
)
AS $$
BEGIN
RETURN QUERY SELECT
t.field1 AS id,
MIN(t.field2) AS test
FROM table t
GROUP BY t.field1
ORDER BY
CASE p_sort_order
WHEN ‘asc’ THEN test END ASC,
WHEN ‘desc’ THEN test END DESC
END
LIMIT p_limit;
END; $$
LANGUAGE 'plpgsql';
这些参数似乎只在 WHERE、LIMIT 等子句中有效,但在 ORDER BY 中无效(尽管我还没有找到任何官方文档)。
实现此目的的解决方法是什么?
根据 link,将您的 select
更改为:
ORDER BY
CASE WHEN p_sort_order = 'asc' THEN min(t.field2) END ASC,
CASE WHEN p_sort_order = 'desc' THEN min(t.field2) END DESC
LIMIT p_limit;
这里的神奇之处在于,case
个实例 return 要么是 test
要么是 null
,后面跟着的是 asc
或 desc
。如果 p_sort_order
是 desc
,那么你会得到:
ORDER BY
NULL ASC,
test DESC
NULL ASC
使所有行在排序规则中相等,因此 order by
落入 test DESC
项。
这对我适用于 PG10(根据您的评论更新):
create or replace function do_sort(p_sort_order text)
returns table (id int, name text)
as $$
begin
return query select users.id, min(users.email)
from users
group by users.id
order by case when p_sort_order = 'asc' then min(users.email) end asc,
case when p_sort_order = 'desc' then min(users.email) end desc
limit 10;
end; $$ language plpgsql;
CREATE FUNCTION
Time: 10.849 ms
select * from do_sort('desc');
┌───────┬───────────────────────┐
│ id │ name │
├───────┼───────────────────────┤
│ 9 │ 9user@example.com │
│ 99 │ 99user@example.com │
│ 999 │ 999user@example.com │
│ 9999 │ 9999user@example.com │
│ 99999 │ 99999user@example.com │
│ 99998 │ 99998user@example.com │
│ 99997 │ 99997user@example.com │
│ 99996 │ 99996user@example.com │
│ 99995 │ 99995user@example.com │
│ 99994 │ 99994user@example.com │
└───────┴───────────────────────┘
(10 rows)
Time: 87.236 ms
select * from do_sort('asc');
┌────────┬────────────────────────┐
│ id │ name │
├────────┼────────────────────────┤
│ 100000 │ 100000user@example.com │
│ 100001 │ 100001user@example.com │
│ 100002 │ 100002user@example.com │
│ 100003 │ 100003user@example.com │
│ 100004 │ 100004user@example.com │
│ 10000 │ 10000user@example.com │
│ 10001 │ 10001user@example.com │
│ 10002 │ 10002user@example.com │
│ 10003 │ 10003user@example.com │
│ 10004 │ 10004user@example.com │
└────────┴────────────────────────┘
(10 rows)
Time: 85.219 ms