Schema :
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
);
Daten :
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)
;
Also haben wir:
- 3 Artikel in CZ in 1 in PL
- 370 in CZ und 25 in PL verdient
- 350 Kosten in CZ und 20 in PL
- 11 extra verdient in CZ und 5 extra verdient in PL
Jetzt möchte ich Antworten auf folgende Fragen erhalten:
- Wie viele Artikel hatten wir letzten Monat in jedem Land?
- Was war der insgesamt verdiente Betrag (Summe der Zahlungen. Beträge) in jedem Land?
- Was waren die Gesamtkosten (Summe der Artikel.Preis) in jedem Land?
- Wie hoch war der zusätzliche Gesamtverdienst (Summe der Extras) in jedem Land?
Mit der folgenden Abfrage ( 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;
Die Ergebnisse sind falsch:
group_by | item_count | cost | earned | extra_earned
----------+------------+--------+--------+--------------
CZ | 3 | 450.00 | 370.00 | 16.00
PL | 1 | 40.00 | 50.00 | 5.00
Kosten und extra_earned für CZ sind ungültig - 450 statt 350 und 16 statt 11. Kosten und verdient für PL sind ebenfalls ungültig - sie werden verdoppelt.
Ich verstehe, dass es im Fall von LEFT OUTER JOIN
2 Zeilen für Artikel mit items.id = 1 gibt (und so weiter für andere Übereinstimmungen), aber ich weiß nicht, wie man eine richtige Abfrage erstellt.
Fragen :
- Wie vermeide ich falsche Ergebnisse bei der Aggregation in Abfragen in mehreren Tabellen?
- Was ist der beste Weg, um die Summe über verschiedene Werte zu berechnen (in diesem Fall items.id)?
PostgreSQL-Version : 9.6.1
Seq Scan
Zahlungen erforderlich , was bedeutet, dass die Statistik für alle Elemente neu berechnet wird. Ich habe dies in der Frage nicht erwähnt, aber ich möchte Elemente auch nach Erstellungszeit filtern, sodass ich nur eine bestimmte Teilmenge der aggregierten Daten benötige. Ich werde die Frage aktualisieren
WHERE
den Unterabfragen Klauseln oder Verknüpfungen hinzufügen. Aktivieren Sie aber auch Option 4 mit LATERAL
.
payments
und items
in Unterabfrage , und fügen Sie WHERE
es? Ich muss alle Optionen vergleichen :)
items.created_at
, ja.
OUTER APPLY
und stattdessenLATERAL
Joins verwenden.