我在Postgresql中有两个表,如下所示:
收据
id CHARACTER VARYING(20),
account CHARACTER VARYING(20),
date DATE,
amount NUMERIC(8,2),
PRIMARY KEY(id)
non_cash
id CHARACTER VARYING(20),
account CHARACTER VARYING(20),
date DATE,
amount NUMERIC(8,2),
PRIMARY KEY(id)
现在,我想从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 中有所不同,其余数字相同。
答案 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