Beschränken Sie die Verknüpfung auf eine Zeile
-
11-12-2019 - |
Frage
Ich habe folgende Abfrage:
SELECT sum((select count(*) as itemCount) * "SalesOrderItems"."price") as amount, 'rma' as
"creditType", "Clients"."company" as "client", "Clients".id as "ClientId", "Rmas".*
FROM "Rmas" JOIN "EsnsRmas" on("EsnsRmas"."RmaId" = "Rmas"."id")
JOIN "Esns" on ("Esns".id = "EsnsRmas"."EsnId")
JOIN "EsnsSalesOrderItems" on("EsnsSalesOrderItems"."EsnId" = "Esns"."id" )
JOIN "SalesOrderItems" on("SalesOrderItems"."id" = "EsnsSalesOrderItems"."SalesOrderItemId")
JOIN "Clients" on("Clients"."id" = "Rmas"."ClientId" )
WHERE "Rmas"."credited"=false AND "Rmas"."verifyStatus" IS NOT null
GROUP BY "Clients".id, "Rmas".id;
Das Problem ist, dass die Tabelle "EsnsSalesOrderItems"
kann das Gleiche haben EsnId
in verschiedenen Einträgen.Ich möchte die Abfrage darauf beschränken, nur den letzten Eintrag abzurufen "EsnsSalesOrderItems"
das hat das gleiche "EsnId"
.
Mit „letzter“ Eintrag meine ich Folgendes:
Derjenige, der in der Tabelle zuletzt erscheint "EsnsSalesOrderItems"
.Also zum Beispiel wenn "EsnsSalesOrderItems"
hat zwei Einträge mit "EsnId" = 6
Und "createdAt" = '2012-06-19'
Und '2012-07-19'
bzw. es sollte mir nur den Eintrag von geben '2012-07-19'
.
Lösung
SELECT (count(*) * sum(s."price")) AS amount
, 'rma' AS "creditType"
, c."company" AS "client"
, c.id AS "ClientId"
, r.*
FROM "Rmas" r
JOIN "EsnsRmas" er ON er."RmaId" = r."id"
JOIN "Esns" e ON e.id = er."EsnId"
JOIN (
SELECT DISTINCT ON ("EsnId") *
FROM "EsnsSalesOrderItems"
ORDER BY "EsnId", "createdAt" DESC
) es ON es."EsnId" = e."id"
JOIN "SalesOrderItems" s ON s."id" = es."SalesOrderItemId"
JOIN "Clients" c ON c."id" = r."ClientId"
WHERE r."credited" = FALSE
AND r."verifyStatus" IS NOT NULL
GROUP BY c.id, r.id;
Ihre Abfrage in der Frage enthält ein ungültiges Aggregat gegenüber einem anderen Aggregat:
sum((select count(*) as itemCount) * "SalesOrderItems"."price") as amount
Vereinfacht und in legale Syntax umgewandelt:
(count(*) * sum(s."price")) AS amount
Aber wollen Sie wirklich mit der Anzahl pro Gruppe multiplizieren?
Ich rufe die einzelne Zeile pro Gruppe ab "EsnsSalesOrderItems"
mit DISTINCT ON
.Ausführliche Erklärung:
Ich habe auch Tabellenaliase und Formatierungen hinzugefügt, um die Abfrage für das menschliche Auge einfacher zu analysieren.Wenn Sie könnten Vermeiden Sie Camel Case, Sie könnten alle doppelten Anführungszeichen loswerden trübt die Sicht.
Andere Tipps
Etwas wie:
join (
select "EsnId",
row_number() over (partition by "EsnId" order by "createdAt" desc) as rn
from "EsnsSalesOrderItems"
) t ON t."EsnId" = "Esns"."id" and rn = 1
Dadurch wird die neueste Version ausgewählt.EsnId"
aus "EsnsSalesOrderItems"
basierend auf der Spalte creation_date
.Da Sie die Struktur Ihrer Tabellen nicht gepostet haben, musste ich einen Spaltennamen „erfinden“.Sie können jede Spalte verwenden, die es Ihnen ermöglicht, eine für Sie passende Reihenfolge der Zeilen festzulegen.
Bedenken Sie jedoch, dass das Konzept der „letzten Reihe“ nur gültig ist, wenn Sie eine Reihenfolge oder die Reihen angeben.Eine Tabelle als solche ist weder geordnet noch das Ergebnis einer Abfrage es sei denn Sie geben eine an order by
nekromancierend, weil die Antworten veraltet sind. Kummer
Nutzen Sie das in
links | Richtig | innerer Join
Ich werde mit einem Beispiel erklären:
Angenommen, Sie haben einen Tisch "Kontakte". Kummer
Nun haben Kontakte organisatorische Einheiten.
Sie können zu einem Zeitpunkt eine Person haben, aber noz in n-Punkte.
Jetzt müssen Sie Kontakte und OU in einem Zeitraum in einem Zeitraum (kein Berichtsdatum, sondern ein Datumsbereich) abfragen, können Sie die Datensatzzählung erhöhen, wenn Sie einfach ein tun linke Verbindung Kummer Um das OUs anzuzeigen, müssen Sie sich also einfach dem ersten OU für jeden Kontakt anschließen (wo das, was zuerst ein beliebiges Kriterium ist, ein willkürliches Kriterium ist, wenn der letzte Wert beispielsweise ein anderer Weg ist, das ist nur eine andere Möglichkeit, den ersten Wert beim Sortieren zu sagen durch absteigende Datumsbestellung).
In SQL-Server würden Sie mit einem Kreuz-Apply (oder eher äußeren Anwenden verwenden, da wir einen linken Join benötigen), der in jeder Zeile eine Tabellenbewertungsfunktion aufgerufen wird, die sie anschließen muss. generasacodicetagpre.
in postgreSQL, ab Version 9.3, Sie können das auch tun - verwenden Sie einfach das Keyword von LATERAL
, um dasselbe zu erreichen:
generasacodicetagpre.
Versuchen Sie es mit einer Unterabfrage in Ihrer On-Klausel.Ein abstraktes Beispiel: generasacodicetagpre.