Skema :
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
);
Data :
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)
;
Jadi kita punya:
- 3 item dalam CZ dalam 1 dalam PL
- 370 diperoleh di CZ dan 25 di PL
- 350 biaya dalam CZ dan 20 dalam PL
- 11 ekstra diperoleh di CZ dan 5 ekstra di PL
Sekarang saya ingin mendapatkan jawaban untuk pertanyaan-pertanyaan berikut:
- Berapa banyak barang yang kami miliki bulan lalu di setiap negara?
- Berapa jumlah total yang diterima (jumlah pembayaran. Jumlah) di setiap negara?
- Berapa total biaya (jumlah barang.harga) di setiap negara?
- Berapa total penghasilan tambahan (jumlah extras.amount) di setiap negara?
Dengan kueri berikut ( 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;
Hasilnya salah:
group_by | item_count | cost | earned | extra_earned
----------+------------+--------+--------+--------------
CZ | 3 | 450.00 | 370.00 | 16.00
PL | 1 | 40.00 | 50.00 | 5.00
Biaya dan extra_earned untuk CZ tidak valid - 450 bukannya 350 dan 16 bukannya 11. Biaya dan diperoleh untuk PL juga tidak valid - mereka digandakan.
Saya mengerti, bahwa dalam kasus LEFT OUTER JOIN
akan ada 2 baris untuk item dengan items.id = 1 (dan seterusnya untuk pertandingan lainnya), tetapi saya tidak tahu bagaimana membangun kueri yang tepat.
Pertanyaan :
- Bagaimana menghindari hasil yang salah dalam agregasi dalam kueri di beberapa tabel?
- Apa cara terbaik untuk menghitung penjumlahan dari nilai yang berbeda (items.id dalam kasus itu)?
Versi PostgreSQL : 9.6.1
Seq Scan
pembayaran, yang berarti bahwa statistik akan dihitung ulang pada semua item. Saya tidak menyebutkan ini dalam pertanyaan, tetapi saya juga ingin memfilter item berdasarkan waktu pembuatan, jadi saya hanya perlu subkumpulan data agregat tertentu. Saya akan memperbarui pertanyaan
WHERE
klausa atau bergabung di subqueries. Tetapi periksa opsi 4 juga, menggunakan LATERAL
.
payments
dan items
dalam subquery dan menambahkannya WHERE
? Saya harus membandingkan semua opsi :)
items.created_at
, ya.
OUTER APPLY
dan menggunakanLATERAL
gabungan.