# 通过多个联接对不同行求和

10

``````CREATE TABLE "items" (
"id"            SERIAL                   NOT NULL PRIMARY KEY,
"country"       VARCHAR(2)               NOT NULL,
"created"       TIMESTAMP WITH TIME ZONE NOT NULL,
"price"         NUMERIC(11, 2)           NOT NULL
);
CREATE TABLE "payments" (
"id"      SERIAL                   NOT NULL PRIMARY KEY,
"created" TIMESTAMP WITH TIME ZONE NOT NULL,
"amount"  NUMERIC(11, 2)           NOT NULL,
"item_id" INTEGER                  NULL
);
CREATE TABLE "extras" (
"id"      SERIAL                   NOT NULL PRIMARY KEY,
"created" TIMESTAMP WITH TIME ZONE NOT NULL,
"amount"  NUMERIC(11, 2)           NOT NULL,
"item_id" INTEGER                  NULL
);``````

``````INSERT INTO items VALUES
(1, 'CZ', '2016-11-01', 100),
(2, 'CZ', '2016-11-02', 100),
(3, 'PL', '2016-11-03', 20),
(4, 'CZ', '2016-11-04', 150)
;
INSERT INTO payments VALUES
(1, '2016-11-01', 60, 1),
(2, '2016-11-01', 60, 1),
(3, '2016-11-02', 100, 2),
(4, '2016-11-03', 25, 3),
(5, '2016-11-04', 150, 4)
;
INSERT INTO extras VALUES
(1, '2016-11-01', 5, 1),
(2, '2016-11-02', 1, 2),
(3, '2016-11-03', 2, 3),
(4, '2016-11-03', 3, 3),
(5, '2016-11-04', 5, 4)
;``````

• PL中1中的CZ中有3个项目
• 捷克（CZ）和波兰（PL）获得25和370
• CZ的费用为350，PL的费用为20
• CZ可多赚11点，PL可多赚5点

1. 我们上个月在每个国家/地区有几件商品？
2. 每个国家的总收入金额（付款总额。金额）是多少？
3. 每个国家的总成本（商品价格总和）是多少？
4. 每个国家的总额外收入（总金额的总和）是多少？

``````SELECT
country                  AS "group_by",
COUNT(DISTINCT items.id) AS "item_count",
SUM(items.price)         AS "cost",
SUM(payments.amount)     AS "earned",
SUM(extras.amount)       AS "extra_earned"
FROM items
LEFT OUTER JOIN payments ON (items.id = payments.item_id)
LEFT OUTER JOIN extras ON (items.id = extras.item_id)
GROUP BY 1;``````

`````` group_by | item_count |  cost  | earned | extra_earned
----------+------------+--------+--------+--------------
CZ       |          3 | 450.00 | 370.00 |        16.00
PL       |          1 |  40.00 |  50.00 |         5.00``````

CZ的Cost和extra_earned无效-450（而不是350）和16（而不是11）无效。PL的成本和收入也无效-它们加倍。

1. 如何避免在多个表的查询中聚合导致错误的结果？
2. 在不同值上计算和的最佳方法是什么（在这种情况下为items.id）？

PostgreSQL版本：9.6.1

ypercubeᵀᴹ

Stranger6667

ypercubeᵀᴹ

Stranger6667

ypercubeᵀᴹ

9

``````SELECT i.country         AS group_by
, COUNT(*)          AS item_count
, SUM(i.price)      AS cost
, SUM(p.sum_amount) AS earned
, SUM(e.sum_amount) AS extra_earned
FROM  items i
LEFT  JOIN (
SELECT item_id, SUM(amount) AS sum_amount
FROM   payments
GROUP  BY 1
) p ON p.item_id = i.id
LEFT  JOIN (
SELECT item_id, SUM(amount) AS sum_amount
FROM   extras
GROUP  BY 1
) e ON e.item_id = i.id
GROUP BY 1;``````

SQL提琴。

### 但是，如果我要过滤`items.created`？

Stranger6667

@ Stranger6667：这取决于。确实，这是一个不同的问题。我在上面添加了一个答案。
Erwin Brandstetter

`LATERAL JOIN`为我工作！谢谢您的
Stranger6667