计算不同行之和的差

时间:2018-09-24 16:56:57

标签: sql postgresql

我想计算来自不同表的两个和之间的差 我的查询:

SELECT a.id AS id, SUM(a.amount) AS total
    FROM atable a
    LEFT JOIN btable b
    ON a.id = b.id
    WHERE a.start_date BETWEEN a.start_date AND '1996-01-01'
    GROUP BY a.id
    ORDER BY a.id;

第一个查询的结果是这样的:

     id |  total
--------+----------
      1 |   999
      2 |   888
      3 |   999
      4 |   111

我的第二个查询:

SELECT b.id AS id, SUM(b.amount) AS total
    FROM atable a
    LEFT JOIN btable b
    ON a.id = b.id
    WHERE a.end_date BETWEEN a.end_date AND '1996-01-01'
    GROUP BY b.id
    ORDER BY b.id;

第二个查询的结果如下:

     id |  total
--------+----------
      1 |   999
      2 |   866
      3 |   330
      4 |    90

我想将两个查询合并为一个,以了解总列之间的差异,以便输出看起来像这样:

     id |  diff
--------+----------
      1 |     0
      2 |    22
      3 |   660
      4 |    21

2 个答案:

答案 0 :(得分:0)

您可以尝试使用条件汇总函数执行SUM,然后从两个SUM结果中减去。

SELECT a.id AS id,  
    SUM(CASE WHEN a.start_date BETWEEN a.start_date AND '1996-01-01' THEN a.amount ELSE 0 END) 
    - SUM(CASE WHEN a.end_date BETWEEN a.end_date AND '1996-01-01' THEN b.amount ELSE 0 END) AS diff
FROM atable a
LEFT JOIN btable b ON a.id = b.id
GROUP BY a.id
ORDER BY a.id;

或者您可以尝试在join上写id子查询,然后做减法运算。

SELECT t1.id, 
       t1.total - t2.total AS diff 
FROM   (SELECT a.id          AS id, 
               Sum(a.amount) AS total 
        FROM   atable a 
               LEFT JOIN btable b 
                      ON a.id = b.id 
        WHERE  a.start_date BETWEEN a.start_date AND '1996-01-01' 
        GROUP  BY a.id 
        ORDER  BY a.id) t1 
JOIN(SELECT b.id          AS id, 
           Sum(b.amount) AS total 
    FROM   atable a 
           LEFT JOIN btable b 
                  ON a.id = b.id 
    WHERE  a.end_date BETWEEN a.end_date AND '1996-01-01' 
    GROUP  BY b.id 
    ORDER  BY b.id) t2 
 ON t1.id = t2.id 

模式(PostgreSQL v9.6)

CREATE TABLE T1(
   id INT,
  total INT
);

INSERT INTO T1 VALUES (1,999);
INSERT INTO T1 VALUES (2,888);
INSERT INTO T1 VALUES (3,999);
INSERT INTO T1 VALUES (4,111);
CREATE TABLE T2(
   id INT,
  total INT
);

INSERT INTO T2 VALUES (1,999);
INSERT INTO T2 VALUES (2,866);
INSERT INTO T2 VALUES (3,330);
INSERT INTO T2 VALUES (4,90);

查询#1

SELECT t1.id, 
       t1.total - t2.total AS diff 
FROM  T1 t1 
JOIN T2 t2 
 ON t1.id = t2.id;

| id  | diff |
| --- | ---- |
| 1   | 0    |
| 2   | 22   |
| 3   | 669  |
| 4   | 21   |

View on DB Fiddle

注意

T1T2可以代替您的子查询。

答案 1 :(得分:0)

与普通表表达式一起使用连接

with t1 as

    (
    SELECT a.id AS id, SUM(a.amount) AS total
        FROM atable a
        LEFT JOIN btable b
        ON a.id = b.id
        WHERE a.start_date BETWEEN a.start_date AND '1996-01-01'
        GROUP BY a.id
        ORDER BY a.id 
    ), 

    t2 as
    (
    SELECT b.id AS id, SUM(b.amount) AS total
        FROM atable a
        LEFT JOIN btable b
        ON a.id = b.id
        WHERE a.end_date BETWEEN a.end_date AND '1996-01-01'
        GROUP BY b.id
        ORDER BY b.id
    ) select t1.id,t1.total-t2.total as diff 
      left join t2 on t1.id=t2.id

或使用全部合并

    with t1 as

    (
    SELECT a.id AS id, SUM(a.amount) AS total
        FROM atable a
        LEFT JOIN btable b
        ON a.id = b.id
        WHERE a.start_date BETWEEN a.start_date AND '1996-01-01'
        GROUP BY a.id
        ORDER BY a.id 
    ), 

    t2 as
    (
    SELECT b.id AS id, SUM(b.amount)*(-1) AS total
        FROM atable a
        LEFT JOIN btable b
        ON a.id = b.id
        WHERE a.end_date BETWEEN a.end_date AND '1996-01-01'
        GROUP BY b.id
        ORDER BY b.id
    ) 
     select a.id,sum(total) as total from(
      select * from t1 union all select * from t2) a group by a.id