从三个不同的表中获取一个值会得到错误的结果 - postgresql

时间:2018-01-13 09:23:18

标签: postgresql join

目标是在任务上获得剩余时间的一个值。我知道我不能将两个连接表相加,但这个简单的查询让我感到困惑:

CREATE TABLE tsk
    (tskid int4, tskhr numeric(8,2));    
INSERT INTO tsk
    (tskid, tskhr)
VALUES
    (1,80.5),
    (2,120.7);

CREATE TABLE hr
    (hrid int4, hrtsk int4, hrqty numeric(8,2));    
INSERT INTO hr
    (hrid,hrtsk, hrqty)
VALUES
    (1,1,40.5),
    (2,2,40.7),
    (3,1,1);

CREATE TABLE inte
    (inteid int4, intetsk int4, inteqty numeric(8,2));    
INSERT INTO inte
    (inteid,intetsk, inteqty)
VALUES
    (1,1,10.5);

所需的输出是

+-------+------+
| tskid |  hr  | 
+-------+------+
|    1  | 28,5 |  (80,5-(40,5+1+10,5)
|    2  |   80 |  (120,7-40,7)
+-------+------+

我的第一次尝试很简单

SELECT    tskid, coalesce(tskhr-hrqty+inteqty,0) 
FROM      tsk
LEFT JOIN hr on hrtsk=tskid
LEFT JOIN inte on intetsk=tskid

输出

+-------+----------+
| tskid | coalesce |
+-------+----------+
|     1 |     50.5 |
|     1 |       90 |
|     2 |        0 |
+-------+----------+

第二次尝试

SELECT    tskid, coalesce(tskhr-(hrqty+inteqty),0)
FROM      tsk
LEFT JOIN (SELECT hrtsk, sum(hrqty)hrqty FROM hr GROUP BY 1) h ON tskid =h.hrtsk
LEFT JOIN (SELECT intetsk, sum(inteqty)inteqty FROM inte GROUP BY 1) i ON tskid =i.intetsk;

给出了这个结果:

+-------+----------+
| tskid | coalesce |
+-------+----------+
|     1 |     28.5 |
|     2 |        0 |
+-------+----------+

第三次尝试总结外部也不正确:

WITH list AS(
SELECT    tskid, tskhr, hrqty, inteqty 
FROM      tsk
LEFT JOIN hr on hrtsk=tskid
LEFT JOIN inte on intetsk=tskid)
SELECT    tskid, coalesce(sum(tskhr-hrqty+inteqty),0) 
FROM      list
GROUP BY  1

结果:

+-------+----------+
| tskid | coalesce |
+-------+----------+
|     1 |    140.5 |
|     2 |        0 |
+-------+----------+

我必须错过一些明显的东西,但我无法弄清楚是什么。

小提琴:http://sqlfiddle.com/#!15/f11f75/28

子查询也没有运气。

TIA,

2 个答案:

答案 0 :(得分:2)

我会为hrinte表使用单独的子查询:

SELECT
    t1.tskid,
    t1.tskhr - COALESCE(t2.hrqty, 0) - COALESCE(t3.inteqty, 0) AS hr
FROM tsk t1
LEFT JOIN
(
    SELECT hrtsk, SUM(hrqty) AS hrqty
    FROM hr
    GROUP BY hrtsk
) t2
    ON t1.tskid = t2.hrtsk
LEFT JOIN
(
    SELECT intetsk, SUM(inteqty) AS inteqty
    FROM inte
    GROUP BY intetsk
) t3
    ON t1.tskid = t3.intetsk;

SQLFiddle

这种方法的工作原理是子查询避免了连接所固有的记录倍增问题。在这种情况下,我们只想计算tsk表中的值一次,但我们需要在其他两个表中按任务ID进行聚合。

答案 1 :(得分:0)

试试这个:

SELECT tskid, tskhr-((select sum(hrqty) ty from hr where hrid = tsk.tskid group by hrid)+ CASE WHEN (SELECT COUNT(*) FROM inte WHERE inteid=tsk.tskid) = 0 THEN 0 ELSE (SELECT intetsk+inteqty FROM inte WHERE inteid=tsk.tskid group by inteid) END) AS hr FROM tsk group by tskid;