Stellen Sie sich folgende Situation vor: Wir haben T1-, T2- und T3-Tabellen, in denen gespeicherte id
und price
Produkte gespeichert sind. Jetzt müssen wir die id
Produkte finden, die maximal price
alle 3 Tabellen haben. Ich habe diese Lösung:
select id
from T1
where price in(
select max(price)
from(
select max(price) as price
from T1
union
select max(price) as price
from T2
union
select max(price) as price
from T3
) temp
)
union
select id
from T2
where price in(
select max(price)
from(
select max(price) as price
from T1
union
select max(price) as price
from T2
union
select max(price) as price
from T3
) temp
)
union
.... same for T3 table.
Ist es möglich, diese Abfrage zu optimieren?
Antworten:
Ich gehe davon aus, dass Sie meinen, Sie möchten den
id
Artikel, der aufgrund der Daten aus allen drei Tabellen am teuersten ist. Für jede Tabelle benötigen Sie denid
und den Preis der Artikel mit dem Höchstpreis in dieser Tabelle. Für eine Tabelle ist das:Es gibt also eine Unterabfrage:
Und Sie müssen einen der
id
Werte mit dem Maximalpreis aus dieser Unterabfrage finden:Beachten Sie, dass die UNION-Abfrage mehr als 3 Zeilen zurückgibt, wenn in einer der Tabellen zwei gleich teure Elemente aufgeführt sind. Wenn zwei oder mehr gleich teure Elemente vorhanden sind, wählt die Abfrage mit dem LIMIT eines aus, und Sie können nicht vorhersagen, welches. Wenn Sie alle
id
Werte von gleich teuren Gegenständen sehen möchten, die am meisten kosten, müssen Sie ein ähnliches Spiel mit verschachtelten Abfragen spielen. Das macht mich wahnsinnig, sollte aber funktionieren:Dies wäre mit einer WITH-Klausel einfacher:
Nicht jedes DBMS unterstützt die WITH-Klausel wie diese, und ich glaube, MySQL ist eines der DBMS in der Kategorie, die diese Unterstützung nicht enthält.
quelle
Wenn Sie im Falle eines Unentschieden alle IDs erhalten möchten, die den gleichen Preis haben (oder aus anderen Gründen strenger sein müssen), verwenden Sie Folgendes
Unter bestimmten Umständen kann es hilfreich sein,
price
nach dem Erstellen der temporären Tabelle einen Index für die Spalte zu erstellen .quelle
create temporary table allthree as SELECT id, price FROM T1 WHERE price = (SELECT MAX(price) FROM T1) ...
Optimierte Version:
quelle
Ich bin mir nicht sicher, ob ich Ihre Frage verstanden habe, aber sollte das nicht genug sein:
Dadurch werden die Maximalwerte für jede Tabelle ermittelt.
quelle
select by id, max(price)
ist dies in SQL nicht zulässig, MySQL erlaubt es jedoch als Erweiterung - es wählt die ID aus, die für Sie am besten geeignet ist.Ich hoffe, dass meine Syntax funktioniert, da ich normalerweise keine MySql-Person bin.
Wenn MySQL über Fensterfunktionen oder CTEs oder CROSS APPLY oder andere Techniken verfügt, die mir nicht bekannt sind, um ganze Zeilen auszuwählen, die eine aggregierte Bedingung erfüllen, kann meine Abfrage verbessert oder vereinfacht werden.
quelle
CTE ist zur Rettung!
Diese Abfrage ruft auch eine Angabe der Tabelle ab, in der das Maximum gefunden wurde.
Die schlechte Nachricht ist: Der Abfrageoptimierer von Postgres "sieht" die Indizes (auf zdate) in den Gewerkschaften nicht und zieht sie nicht in die Hauptabfrage hoch. Der Abfrageplan besteht aus verschachtelten sequentiellen Scans.
quelle