考虑以下查询:
SELECT DISTINCT ON (ser.id) *
FROM server ser
LEFT JOIN subscription sub ON ser.id = sub.server_id
WHERE (
COUNT(SELECT err.id FROM error err WHERE ser.id = err.id) > 0
OR SUM(SELECT pay.amount FROM payment pay WHERE ser.id = pay.id) > 0
);
此处,将返回正在订阅并且有错误或付款的唯一服务器列表。
但是,我想要返回服务器ID,错误数量和付款总额,而不是返回所有服务器列(*)。例如,初始选择应如下所示:
SELECT DISTINCT ON (ser.id) ser.id, countErrors, sumPayments
选择ser.id是直截了当的,但如何从聚合函数中选择countErrors和sumPayments" count"和"总和" (考虑到它们是WHERE子句中的条件)?
我想象着"其中"条件看起来像这样:
COUNT(SELECT err.id FROM error err WHERE ser.id = err.id) AS countErrors > 0
OR SUM(SELECT pay.amount FROM payment pay WHERE ser.id = pay.id) AS sumPayments > 0
有可能这样做吗?如果是这样,怎么能实现呢?
测试数据如下所示:
server
+----+
| id |
+----+
| 1 |
+----+
| 2 |
+----+
| 3 |
+----+
| 4 |
+----+
subscription
+----+-----------+
| id | server_id |
+----+-----------+
| 1 | 1 |
+----+-----------+
| 2 | 2 |
+----+-----------+
| 3 | 2 |
+----+-----------+
| 4 | 3 |
+----+-----------+
| 5 | 3 |
+----+-----------+
error
+----+-----------+
| id | server_id |
+----+-----------+
| 1 | 1 |
+----+-----------+
| 3 | 4 |
+----+-----------+
payment
+----+-----------+--------+
| id | server_id | amount |
+----+-----------+--------+
| 1 | 1 | 200 |
+----+-----------+--------+
| 2 | 2 | 200 |
+----+-----------+--------+
| 3 | 2 | 100 |
+----+-----------+--------+
测试数据的结果:
+-----------+-------------+-------------+
| server_id | countErrors | sumPayments |
+-----------+-------------+-------------+
| 1 | 1 | 200 |
+-----------+-------------+-------------+
| 2 | 0 | 300 |
+-----------+-------------+-------------+
答案 0 :(得分:2)
除非我遗漏了什么,否则我会按如下方式编写您的查询。在单独的真实子查询中执行错误和付款的聚合,并加入它们。此外,还有subscription
表的连接,但这仅用于过滤掉没有订阅的服务器。最后,WHERE
子句删除任何没有错误或付款的服务器。
SELECT
s.id AS server_id,
COALESCE(e.countErrors, 0) AS countErrors,
COALESCE(p.sumPayments, 0) AS sumPayments
FROM server s
INNER JOIN
(
SELECT DISTINCT server_id
FROM subscription
) su
ON s.id = su.server_id
LEFT JOIN
(
SELECT server_id, COUNT(*) AS countErrors
FROM error
GROUP BY server_id
) e
ON s.id = e.server_id
LEFT JOIN
(
SELECT server_id, SUM(amount) AS sumPayments
FROM payment
GROUP BY server_id
) p
ON s.id = p.server_id
WHERE
p.sumPayments > 0 OR
e.countErrors > 0
ORDER BY
s.id;
答案 1 :(得分:1)
这里的错误是将COUNT放在SELECT之外,它需要进入内部:
(SELECT COUNT(err.id) FROM error err WHERE ser.id = err.id) > 0
OR (SELECT SUM(pay.amount) FROM payment pay WHERE ser.id = pay.id) > 0