Lược đồ :
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
);
Dữ liệu :
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)
;
Vì vậy chúng tôi có:
- 3 mặt hàng trong CZ trong 1 ở PL
- 370 kiếm được ở CZ và 25 ở PL
- 350 chi phí ở CZ và 20 ở PL
- 11 kiếm thêm ở CZ và 5 kiếm thêm ở PL
Bây giờ tôi muốn nhận câu trả lời cho các câu hỏi sau:
- Có bao nhiêu mặt hàng chúng tôi đã có tháng trước ở mỗi quốc gia?
- Tổng số tiền kiếm được (tổng số thanh toán.amounts) ở mỗi quốc gia là bao nhiêu?
- Tổng chi phí (tổng các mặt hàng.price) ở mỗi quốc gia là bao nhiêu?
- Tổng thu nhập thêm (tổng của Extra.amount) ở mỗi quốc gia là bao nhiêu?
Với truy vấn sau ( SQLFiddle ):
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;
Kết quả sai:
group_by | item_count | cost | earned | extra_earned
----------+------------+--------+--------+--------------
CZ | 3 | 450.00 | 370.00 | 16.00
PL | 1 | 40.00 | 50.00 | 5.00
Chi phí và chi phí thêm cho CZ không hợp lệ - 450 thay vì 350 và 16 thay vì 11. Chi phí và kiếm được cho PL cũng không hợp lệ - chúng được nhân đôi.
Tôi hiểu rằng trong trường hợp LEFT OUTER JOIN
sẽ có 2 hàng cho mục có mục.id = 1 (và cứ thế cho các trận đấu khác), nhưng tôi không biết cách tạo một truy vấn phù hợp.
Câu hỏi :
- Làm thế nào để tránh kết quả sai trong tổng hợp trong các truy vấn trên nhiều bảng?
- Cách tốt nhất để tính tổng trên các giá trị riêng biệt (items.id trong trường hợp đó) là gì?
Phiên bản PostgreSQL : 9.6.1
Seq Scan
thanh toán, điều đó có nghĩa là thống kê sẽ được tính toán lại trên tất cả các mục. Tôi đã không đề cập đến vấn đề này trong câu hỏi nhưng tôi cũng muốn lọc các mục theo thời gian tạo, vì vậy tôi sẽ chỉ cần tập hợp con cụ thể của dữ liệu tổng hợp. Tôi sẽ cập nhật câu hỏi
WHERE
các mệnh đề hoặc tham gia trong các truy vấn con. Nhưng kiểm tra tùy chọn 4, quá, sử dụng LATERAL
.
payments
và items
trong truy vấn con và thêm WHERE
vào nó? Tôi sẽ cần điểm chuẩn tất cả các tùy chọn :)
items.created_at
, có.
OUTER APPLY
và sử dụng các phépLATERAL
nối thay thế.