Hom*_*lli 1 sql postgresql plpgsql
我遇到过这个"voodoo"SQL,它用于从表中执行自定义数据分组.我想知道它是如何做到的,但是我无法理解它.一位SQL专家可以用简单的英语向那些不太熟悉SQL的人解释这个片段的各个部分,它可以让它发挥其魔力吗?
select ceil(rnk/10.0) as grp,
col1, col2, col3, col4, col5, col6, col7
from (select e.col1, e.col2, e.col3, e.col4, e.col5, e.col6, e.col7,
(select count(*)
from mytable d
where e.col1 > d.col1)+1 as rnk
from mytable e) x
order by grp;
Run Code Online (Sandbox Code Playgroud)
上面我无法理解的SQL部分是返回列'x'的内部SQL:
(select count(*) from mytable d
where e.col1 > d.col1)+1 as rnk
from mytable e
) x
Run Code Online (Sandbox Code Playgroud)
我希望能够自己运行该查询:
select count(*) from mytable d
where e.col1 > d.col1)+1 as rnk
from mytable e
Run Code Online (Sandbox Code Playgroud)
但是,当我这样做时,我收到错误:
错误:语法错误在"+"处或附近第2行:其中e.col1> d.col1)+1为rnk
那么,那里发生了什么?!
此外,当前的SQL使用数字10进行硬编码.我想在其周围包装一个函数,以便能够使用10以外的数字调用该函数.
后端数据库是PostgreSQL,因此该函数将在PL/pgSQL中.这是我第一次尝试编写这样的函数 - 但是,这不太正确,因为我想返回指定列的多行 - 所以下面的函数需要稍微修改,不完全确定如何:
CREATE OR REPLACE FUNCTION my_custom_grouping(in integer,
out grp integer,
out col1 double,
out col2 double,
out col3 double,
out col4 double,
out col5 double,
out col6 double,
out col7 double
)
AS $$ SELECT
ceil(rnk/$1) as grp,
col1, col2, col3, col4, col5, col6, col7
from (
select e.col1, e.col2, e.col3, e.col4, e.col5, e.col6, e.col7,
(select count(*) from mytable d
where e.col1 > d.col1)+1 as rnk
from mytable e
) x
order by grp;
$$
LANGUAGE SQL;
Run Code Online (Sandbox Code Playgroud)
除了函数不返回多行之外,我不确定这是否是参数化查询的最佳方法 - 我是否在正确的路径上? - 如果是,我如何修改上面的函数以返回多行而不是当前的单个"行"(即"多列"输出)?
这是从函数返回的数据运行聚合函数(按'grp'分组)的正确方法吗?
你的(简化!)函数可能如下所示:
CREATE OR REPLACE FUNCTION my_custom_grouping(integer)
RETURNS TABLE (
grp integer,
col1 double precision,
col2 double precision,
col3 double precision,
col4 double precision,
col5 double precision,
col6 double precision,
col7 double precision) AS
$BODY$
SELECT ceil(rank() OVER (ORDER BY col1) / $1)::int as grp
,col1, col2, col3, col4, col5, col6, col7
FROM mytable
ORDER BY 1;
$BODY$ LANGUAGE SQL;
Run Code Online (Sandbox Code Playgroud)
请注意,这language SQL不是PL/pgSQL函数.你也可以使用language plpgsql,但这里没有必要.
我用窗口函数rank()替换了伏都教的核心,它应该完全相同,更简单.
我也完全删除了子查询.没有必要.
该类型在PostgreSQL中double调用double precision.
要返回多行,请按照RETURNS SETOF record或RETURNS TABLE按我的方式定义函数.
ORDER BY可以使用位置参数,因此您不必再次拼出第一列的计算:ORDER BY 1.
但是,同一行中有多行grp.向ORDER BY子句添加更多列或表达式以获得稳定的排序顺序.