对于下面提到的案例,是否可以有1个查询而不是2个查询?

时间:2015-08-20 16:23:14

标签: sql postgresql select

我在Postgresql中有两个表,如下所示:

  1. 收据

    id CHARACTER VARYING(20),
    account CHARACTER VARYING(20),
    date DATE,
    amount NUMERIC(8,2),
    PRIMARY KEY(id)
    
  2. non_cash

    id CHARACTER VARYING(20),
    account CHARACTER VARYING(20),
    date DATE,
    amount NUMERIC(8,2),
    PRIMARY KEY(id)
    
  3. 现在,我想从SUM(amount)的两个表中account = '00210_pre'SUM(amount)以及MAX(date)两个表格中选择account = '00210_int'。我可以使用2个查询获得所需的结果:

    SELECT SUM(amount) AS int_total, MAX(date)
    FROM (SELECT amount, date, account FROM non_cash
    UNION SELECT amount, date, account FROM receipts) AS v
    WHERE account = '00210_int'
    

    SELECT SUM(amount) AS pre_total
    FROM (SELECT amount, account FROM non_cash
    UNION SELECT amount, account FROM receipts) AS v
    WHERE account = '00210_pre'
    

    现在我的问题是是否可以在一个查询中使用上述内容?如果是,如何?

    请注意,该帐户的后缀仅在 _pre _int 中有所不同,其余数字相同。

2 个答案:

答案 0 :(得分:1)

您不应该使用UNION。您应该使用UNION ALL,因为UNION会删除重复项,这可能是不可取的,并且是浪费精力。但是,您的问题的答案是GROUP BY

SELECT account, SUM(amount) AS int_total, MAX(date)
FROM ((SELECT amount, date, account FROM non_cash
      ) UNION ALL
      (SELECT amount, date, account FROM receipts)
     ) v
WHERE account IN ('00210_int', '00210_pre')
GROUP BY account;

注意:如果要组合值,请不要使用GROUP BY

SELECT SUM(amount) AS int_total, MAX(date)
FROM ((SELECT amount, date, account FROM non_cash
      ) UNION ALL
      (SELECT amount, date, account FROM receipts)
     ) v
WHERE account IN ('00210_int', '00210_pre');

编辑:

要获得单行使用条件聚合:

SELECT SUM(CASE WHEN account = '00210_int' THEN amount ELSE 0 END) AS int_total,
       SUM(CASE WHEN account = '00210_pre' THEN amount ELSE 0 END) AS pre_total,
       MAX(date)
FROM ((SELECT amount, date, account FROM non_cash
      ) UNION ALL
      (SELECT amount, date, account FROM receipts)
     ) v
WHERE account IN ('00210_int', '00210_pre');

答案 1 :(得分:0)

SELECT left(nc.account,5) account, 
    max(greatest(nc.date, r.date)) max_date,
    sum(nc.amount + r.amount) total
    sum(CASE WHEN nc.account = '00210_int' OR r.account = '00210_int' THEN 
            nc.amount + r.amount
            ELSE NULL
            END
            ) int_total,
    sum(CASE WHEN nc.account = '00210_pre' OR r.account = '00210_pre' THEN 
            nc.amount + r.amount
            ELSE NULL
            END
            ) pre_total
FROM non_cash nc
INNER JOIN receipts r
ON left(nc.account,5) = left(r.account,5)
WHERE nc.account  IN ( '00210_int', '00210_pre')
OR r.account  IN ( '00210_int', '00210_pre')
GROUP BY 1