【问题标题】:Function in PostgreSQL to insert from one table to another?PostgreSQL中的函数从一个表插入到另一个表?
【发布时间】:2015-01-25 10:57:57
【问题描述】:

我有以下:

我拿到了桌子:

Equipos(团队)

Partidos(比赛)

partidos 表中的 num_eqpo_loc 和 num_eqpo_vis 列引用了表 equipo。他们引用了 num_eqpo 列。 正如你在这里看到的:

create table equipos
(num_eqpo serial,     
ciudad varchar (30),
num_gpo int, 
nom_equipo varchar (30), 
primary key (num_eqpo), 
foreign key (num_gpo) references grupos (num_gpo))

create table partidos 
(semana int, 
num_eqpo_loc int, 
num_eqpo_vis int, 
goles_loc int, 
goles_vis int, primary key (semana,num_eqpo_loc,num_eqpo_vis), 
foreign key (num_eqpo_loc) references equipos (num_eqpo), 
foreign key (num_eqpo_vis) references equipos (num_eqpo))

我想得到以下输出:

一方面,我创建了一个名为 general 的表:

CREATE TABLE general
(
  equipo character varying(30) NOT NULL,
  partidos_jug integer,
  partidos_gana integer,
  partidos_emp integer,
  partidos_perd integer,
  puntos integer,
  goles_favor integer,
  CONSTRAINT general_pkey PRIMARY KEY (equipo)
)

另一方面,我有这个功能:

CREATE OR REPLACE FUNCTION sp_tablageneral ()  RETURNS TABLE (
    equipo character varying(30)
  , partidos_jug int
  , partidos_gana int
  , partidos_emp int
  , partidos_perd int
  , puntos int
  , goles_favor int) AS
$BODY$
DECLARE cont int:= (SELECT count(num_eqpo)FROM equipos);
r partidos%ROWTYPE;
BEGIN

    while cont>0
    LOOP

    SELECT INTO equipo nom_equipo FROM equipos AS E WHERE E.num_eqpo=cont;
    SELECT INTO partidos_jug COUNT(*) FROM partidos as P WHERE (P.num_eqpo_loc=cont OR P.num_eqpo_vis=cont);
    SELECT INTO partidos_gana COUNT(*) FROM partidos AS P WHERE (P.num_eqpo_loc=cont AND P.goles_loc>P.goles_vis OR P.num_eqpo_vis=cont AND P.goles_vis>P.goles_loc);
    SELECT INTO partidos_emp COUNT(*) FROM partidos AS P WHERE (P.num_eqpo_loc=cont AND P.goles_loc=P.goles_vis OR P.num_eqpo_vis=cont AND P.goles_loc=P.goles_vis);
    SELECT INTO partidos_perd COUNT(*) FROM partidos as P WHERE ( (P.num_eqpo_loc=cont AND P.goles_loc<P.goles_vis) OR (P.num_eqpo_vis=cont AND P.goles_loc>P.goles_vis));
    SELECT INTO puntos partidos_emp*1 + partidos_gana*3;
    SELECT INTO goles_favor SUM(goles_loc) FROM partidos as P WHERE P.num_eqpo_loc=cont + (SELECT SUM(goles_vis) FROM partidos as P WHERE P.num_eqpo_vis=cont);

    cont:= cont - 1;
    END LOOP;

  RETURN NEXT ; 
 END;
$BODY$ LANGUAGE plpgsql STABLE;

我希望函数显示我所需的输出,并且我还希望表“常规”具有与所需输出相同的值。

有了这个功能,我就得到了:

我刚拿到第一行数据,不知道怎么看到想要的内容。 我也想知道如何从函数返回的表中插入到名为 General 的现有表中。

编辑:我也尝试过:

CREATE OR REPLACE FUNCTION sp_tablageneral ()  RETURNS TABLE (
    equipo character varying(30)
  , partidos_jug int
  , partidos_gana int
  , partidos_emp int
  , partidos_perd int
  , puntos int
  , goles_favor int) AS
$BODY$
DECLARE cont int:= (SELECT count(num_eqpo)FROM equipos);
r partidos%ROWTYPE;
BEGIN

    while cont>0
    LOOP

        SELECT INTO equipo nom_equipo FROM equipos AS E WHERE E.num_eqpo=cont;
    SELECT INTO partidos_jug COUNT(*) FROM partidos as P WHERE (P.num_eqpo_loc=cont OR P.num_eqpo_vis=cont);
    SELECT INTO partidos_gana COUNT(*) FROM partidos AS P WHERE (P.num_eqpo_loc=cont AND P.goles_loc>P.goles_vis OR P.num_eqpo_vis=cont AND P.goles_vis>P.goles_loc);
    SELECT INTO partidos_emp COUNT(*) FROM partidos AS P WHERE (P.num_eqpo_loc=cont AND P.goles_loc=P.goles_vis OR P.num_eqpo_vis=cont AND P.goles_loc=P.goles_vis);
    SELECT INTO partidos_perd COUNT(*) FROM partidos as P WHERE ( (P.num_eqpo_loc=cont AND P.goles_loc<P.goles_vis) OR (P.num_eqpo_vis=cont AND P.goles_loc>P.goles_vis));
    SELECT INTO puntos partidos_emp*1 + partidos_gana*3;
    SELECT INTO goles_favor SUM(goles_loc) FROM partidos as P WHERE P.num_eqpo_loc=cont + (SELECT SUM(goles_vis) FROM partidos as P WHERE P.num_eqpo_vis=cont);

    SELECT equipo, partidos_jug , partidos_gana, partidos_emp , partidos_perd , puntos , goles_favor INTO equipo,partidos_jug,partidos_gana,partidos_emp,partidos_perd,puntos,goles_favor FROM general;

    cont:= cont - 1;
        END LOOP;

  RETURN NEXT ; 
 END;
$BODY$ LANGUAGE plpgsql STABLE;

但我明白了:

ERROR: the reference to the column "equipo" is ambiguous 
LINE 1: SELECT equipo , partidos_jug, partidos_gana, partidos_emp ...
                ^
********** Error **********
ERROR: the reference to the column "equipo" is ambiguous 
SQL state: 42702
Detail: It could refer either to a variable PL / pgSQL as a column in a table.
Context: PL / pgSQL sp_tablageneral () function on line 17 in SQL statement

任何帮助都会很棒。

提前致谢!

【问题讨论】:

    标签: postgresql insert


    【解决方案1】:

    你可以用纯 SQL 解决这个问题,你不需要一个函数。

    最好的办法是将统计数据的收集分成两个不同的查询,一个用于球队主场比赛,一个用于客场比赛。为每场比赛计算得分和进球数。然后UNION 这两个查询并将其用作子查询来计算整体统计信息:

    SELECT
      eq.nom_equipo AS equipo,
      COUNT(p.*) AS partidos_jug,
      SUM(CASE WHEN p.puntos = 3 THEN 1 ELSE 0 END) partidos_gana,
      SUM(CASE WHEN p.puntos = 1 THEN 1 ELSE 0 END) partidos_emp,
      SUM(CASE WHEN p.puntos = 0 THEN 1 ELSE 0 END) partidos_perd,
      SUM(p.puntos) AS puntos,
      SUM(p.goles) AS goles_favor
    FROM equipos eq
    JOIN (
      -- Playing at home
      SELECT
        num_eqpo_loc AS eqpo, 
        CASE WHEN (goles_loc > goles_vis) THEN 3
             WHEN (goles_loc = goles_vis) THEN 1
             ELSE 0
        END AS puntos,
        goles_loc AS goles
      FROM partidos
      UNION
      -- Playing away
      SELECT
        num_eqpo_vis AS eqpo, 
        CASE WHEN (goles_vis > goles_loc) THEN 3
             WHEN (goles_vis = goles_loc) THEN 1
             ELSE 0
        END AS puntos,
        goles_vis AS goles
      FROM partidos) AS p ON p.eqpo = eq.num_eqpo
    GROUP BY equipo
    ORDER BY puntos DESC, partidos_jug ASC, goles_favor DESC;
    

    由于CASE 语句,这并不是特别快,但它会比使用过程和循环更快。

    我建议您使用上述查询CREATE VIEW general AS ...,而不是将此查询的结果放入表中。在这种情况下,当您 SELECT * FROM general 时,您总是会得到最新的结果,并且您不必在运行查询之前 TRUNCATE 通用表(在表中添加带有数据的新结果将违反 PK 约束)。如果您确实需要该表,请在上面的查询中使用SELECT ... INTO general FROM ...

    【讨论】:

    • 感谢您的回答。不幸的是,我必须为这种情况使用一个函数。
    • @MikePérez 你能解释一下为什么会这样吗?使用函数会更慢。但如果必须:您可以将整个查询包装在 SQL 函数中。
    • 哈哈我知道,很多时候使用不同的东西比使用函数更快。我在课堂上的函数章节,这就是为什么我必须使用函数
    猜你喜欢
    • 2011-10-17
    • 2017-03-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-09-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多