汇总到' plain'询问

时间:2016-06-28 18:12:01

标签: sql database postgresql query-optimization

我有一个查询,它使用聚合函数将maximum absolute值分配给表中的另一列。问题是它需要花费大量时间(apprx。加上10-15秒)来查询完成时间。这就是查询的样子:

UPDATE calculated_table c 
    SET tp = (SELECT MAX(ABS(s.tp)) 
                FROM ts s INNER JOIN tc t ON s.id = t.id
                GROUP BY s.id);

id不唯一,因此分组。 tp是一个数字整数字段。这是表格的样子:

TABLE ts
       PID(primary)       |            id (FKEY)             |                      tp (integer)                   
--------------------+-----------------------------+------------------------------------------------------
 1                        | 2                                | -100
 2                        | 2                                | -500
 3                        | 2                                | -1000

TABLE tc
       PID(primary)       |            id (FKEY)                              
--------------------+-----------------------------+-------------------------
 1                        | 2                               

我希望输出看起来像:

TABLE c
       PID(primary)       |         tp (integer)                   
--------------------+-----------------------------+--------
 1                        | 1000                                

我试图让它像这样工作:

UPDATE calculated_table c 
    SET tp = (SELECT s.tp
                FROM ts s INNER JOIN tc t ON s.id = t.id
                ORDER BY s.tp DESC
                LIMIT 1);

虽然它改善了性能,但结果不正确..任何帮助都会受到赞赏吗?

4 个答案:

答案 0 :(得分:2)

我确实设法修改了查询,结果嵌套aggregate functions不是一个好选择。但是,如果它对任何人都有帮助,那么我最终会做的就是:

UPDATE calculated_table c 
    SET tp = (SELECT ABS(s.trade_position)
                FROM ts s INNER JOIN tc t ON s.id = t.id
                WHERE c.id = s.id
                ORDER BY ABS(s.tp) DESC
                LIMIT 1);

答案 1 :(得分:1)

  

虽然它改善了性能,但结果不正确。

手术成功,但患者死亡。

您的查询存在的问题是

SELECT MAX(ABS(s.tp)) 
  FROM ts s INNER JOIN tc t ON s.id = t.id
  GROUP BY s.id);

不会产生标量值;它会生成一个值,每个s.id一个。您的DBMS确实应该引发语法错误。在性能方面,我认为您将子查询生成的每一行按顺序应用于目标表中的每一行。它可能既慢又错。

您想要的是将select输出与您正在更新的表相关联,并将更新的行限制为相关的行。这是ANSI语法从一个表更新另一个表:

UPDATE calculated_table
SET tp = (SELECT MAX(ABS(s.tp)) 
            FROM ts s INNER JOIN tc t ON s.id = t.id
            where s.id = calculated_table.id)
where exists ( select 1 from ts join tc
               on ts.id = tc.id
               where ts.id = calculated_table.id )

那应该接近你想要的。

顺便说一下,从字面上解释相关子查询很有诱惑力,认为子查询运行 N 次,对目标表中的每一行都运行一次。这是正确的描绘方式,逻辑。 DBMS不会以这种方式实现它,但很可能,性能应该比图片所表明的要好得多。

答案 2 :(得分:0)

尝试:

UPDATE calculated_table c 
    SET tp = (SELECT greatest( MAX( s.tp ) , - MIN( s.tp ))
                FROM ts s INNER JOIN tc t ON s.id = t.id
                WHERE c.id = s.id
              );

还尝试在ts( id, tp )

上创建多列索引

答案 3 :(得分:0)

我希望下面的sql对你有所帮助,我在netezza中测试过,但不是postgresql。另外,我没有把更新放在它上面。

SELECT ABS(COM.TP) 从TC C LEFT OUTER JOIN
(SELECT ID,TP 来自TS A. 什么不存在(选择1                   来自TS B.           在哪里A.ID = B.ID            和ABS(B.TP)> ABS(A.TP)))COM ON C.ID = COM.ID