有人能解释一下这个SQL吗?(我如何将其参数化并作为函数调用?)
我遇到了这段“voodoo”SQL,它用于执行表中数据的自定义分组。我想了解它是如何变魔术的,但我无法摸索。一位SQL专家能不能用简单的英语向不太懂SQL的人解释一下这个代码片段的各个部分,让它发挥神奇的作用有人能解释一下这个SQL吗?(我如何将其参数化并作为函数调用?),sql,postgresql,plpgsql,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 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;
上面的SQL中我似乎无法理解的部分是返回列“x”的内部SQL:
(select count(*) from mytable d
where e.col1 > d.col1)+1 as rnk
from mytable e
) x
我希望能够自行运行该查询:
select count(*) from mytable d
where e.col1 > d.col1)+1 as rnk
from mytable e
但是,当我这样做时,我会得到一个错误:
错误:第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;
除了函数不返回多行之外,我不确定这是否是参数化查询的最佳方法-我在正确的路径上吗如果是,我将如何修改上述函数以返回多行,而不是当前的单个“行”(即“多列”输出)
这是对函数返回的数据运行聚合函数(按“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;
要点:
- 请注意,这不是PL/pgSQL函数。您也可以使用
,但这里不需要这样做语言plpgsql
- 我把你的巫毒核心换成了,应该是一样的,只是更简单而已
- 我还完全删除了子查询。这是没有必要的
- 在PostgreSQL中调用类型
double
- 若要返回多行,请将函数定义为
或与我所做的一样RETURNS SETOF record
可以使用位置参数,因此您不必再次详细说明第一列的计算:orderby
orderby 1
但是,同一
中有多行。将更多列或表达式添加到grp
子句中,以获得稳定的排序顺序ORDER BY
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;
要点:
- 请注意,这不是PL/pgSQL函数。您也可以使用
,但这里不需要这样做语言plpgsql
- 我把你的巫毒核心换成了,应该是一样的,只是更简单而已
- 我还完全删除了子查询。这是没有必要的
- 在PostgreSQL中调用类型
double
- 若要返回多行,请将函数定义为
或与我所做的一样RETURNS SETOF record
可以使用位置参数,因此您不必再次详细说明第一列的计算:orderby
orderby 1
但是,同一
中有多行。将更多列或表达式添加到grp
子句中,以获得稳定的排序顺序ORDER BY
e.col1
。但是,整个构造是无效的,因为我们可以使用窗口函数rank()
。我在回答中使用了它。我已重新格式化了初始查询-这可能会使其内部发生的情况更清楚一些。您不能单独运行子查询,因为它引用外部查询:e.col1
。但是,整个构造是无效的,因为我们可以使用窗口函数rank()
。我在回答中使用了它。我已重新格式化了初始查询-这可能会使其内部发生的事情更加清晰。+1用于指向窗口功能的链接-它打开了一个全新的世界(意料之外的双关语!)。+1用于指向窗口功能的链接-它打开了一个全新的世界(意料之外的双关语!)。