Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/postgresql/10.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Function 带IF-ELSE语句的postgresql plpsql函数_Function_Postgresql_If Statement - Fatal编程技术网

Function 带IF-ELSE语句的postgresql plpsql函数

Function 带IF-ELSE语句的postgresql plpsql函数,function,postgresql,if-statement,Function,Postgresql,If Statement,假设我有一个名为t的表,它存储在postgresql数据库中。 我有6列,分别命名为a、b、c、d、e、f。 a、b和c列的值介于0和100之间,但在算术标度上为0

假设我有一个名为t的表,它存储在postgresql数据库中。 我有6列,分别命名为a、b、c、d、e、f。 a、b和c列的值介于0和100之间,但在算术标度上为0 我想计算d、e和f列的加权平均值,但条件与a、b和c列有关。条件是,平均值将仅在值小于50的a、b和c列上计算

我认为这需要一个函数,所以我开始这样做:

CREATE OR REPLACE FUNCTION example(t character varying, a character varying, b character varying, c character varying, d character varying, e character varying, f character varying, g character varying) RETURNS double precision AS $$

BEGIN
    ALTER TABLE t ADD COLUMN g double precision;
        UPDATE t
            IF a > 50 THEN
                SET g = d;
            ELSE 
                IF b > 50 THEN;
                    SET g = (d+e)/2;
                END IF c > 50 THEN
                        SET g = (d+e+f)/3;
            END IF;
END;
$$ LANGUAGE plpgsql;
我得到以下错误:

ERROR:  syntax error at or near "$1"
LINE 1: ALTER TABLE  $1  ADD COLUMN  $2  double precision
                 ^
QUERY:  ALTER TABLE  $1  ADD COLUMN  $2  double precision
CONTEXT:  SQL statement in PL/PgSQL function "example" near line 2

********** Error **********

ERROR: syntax error at or near "$1"
SQL state: 42601
Context: SQL statement in PL/PgSQL function "example" near line 2

有人能告诉我我错了吗,这样我就可以继续计算所需的平均值了?

错误的直接原因是命名冲突。您可以定义参数
t
g
,并在
ALTER TABLE
语句中使用相同的名称。我习惯于在参数名称前面加前缀(如
\u t
\u g
),这样它们就不会与函数体中的其他名称冲突

此外,您的参数不应定义为字符变化,因为它们包含数值。使用适当的,可能是双精度的

但我认为你根本不需要函数。这可以通过简单的SQL语句来解决:

ALTER TABLE tbl ADD COLUMN g double precision;

UPDATE tbl
SET g = CASE
           WHEN a > 50 THEN d 
           WHEN b > 50 THEN (d+e)/2
           WHEN c > 50 THEN (d+e+f)/3
           ELSE 0  -- definition for ELSE case is missing
        END;
您还可以完全忽略整个想法,并使用视图来实现此目的,因为
g
仅保存功能相关的数据:

CREATE VIEW tbl_with_g AS
SELECT *
     , CASE
          WHEN a > 50 THEN d 
          WHEN b > 50 THEN (d+e)/2
          WHEN c > 50 THEN (d+e+f)/3
          ELSE 0
       END AS g
FROM   tbl;

我完全同意欧文回答的所有问题,但我想指出另一个选择。您可以创建一种“生成列”,该列将根据需要进行计算,如下所示:

CREATE FUNCTION g(rec t)
  RETURNS double precision
  IMMUTABLE
  LANGUAGE SQL
AS $$
  SELECT CASE
           WHEN $1.a > 50 THEN $1.d 
           WHEN $1.b > 50 THEN ($1.d+$1.e)/2
           WHEN $1.c > 50 THEN ($1.d+$1.e+$1.f)/3
           ELSE 0
         END;
$$;
然后,只要引用由表名或别名限定,就可以像引用列一样引用
g
。例如:

SELECT *, t.g FROM t;

当一个明显的限定列引用没有解析为一个列时,PostgreSQL planner将查找一个以该表的记录类型作为其唯一参数的同名函数,并执行该函数。有时,这种方法比使用视图更方便,尽管效果基本相同。

不能以这种方式将表名作为参数传递。但是,每次运行该函数时添加一个新列似乎毫无用处。你为什么要这么做?谢谢你的分数!关于SET命令,indedd是错误的。但我可以在集合内使用IF吗?我将如何使用它?”如果a>50',则更新t集g=D?谢谢你的分数!但函数中未使用参数?在我定义它们之后,我应该添加要在函数中使用的变量?关于您对CASE函数的想法,我在创建函数之前已经应用了。它确实计算了一些东西,但当我进行验证时,似乎在CASE函数中不能使用不同的列,因为如果第一个when条件为true,则计算将停止。因此,当第一个条件为true时,该值被设置为d,但第二个条件未被计算,但这就是我需要的,当条件为false时,进行平均。@MihaiNiculita那么您应该调整您的条件,使其相互排斥。如果您希望在
b>50
时跳过第一个
THEN
子句,那么在
时将其用作第一个
a>50和b50,而不是b>50
)。+1 PostgreSQL的一个很酷的功能!出现了一个相关的问题,我补充了一个详细的解释,解释了为什么这样做有效: