MySQL - Kombination von zwei select-Anweisungen in eine Folge mit GRENZWERT effizient
Für eine dating-Anwendung, ich habe ein paar Tabellen, die ich brauche, um die Abfrage für eine einzelne Leistung mit einem LIMIT von 10 beide Abfragen kombiniert. Es scheint schwer zu tun im moment, obwohl es nicht ein Problem für die Abfrage Sie Sie separat, aber die BEGRENZUNG auf 10 wird nicht funktionieren, da die zahlen nicht exakt (ex. nicht LIMIT 5 und LIMIT 5, eine Abfrage 0 Zeilen zurück, während die anderen 10, je nach Szenario).
members table
member_id | member_name
------------------------
1 Herb
2 Karen
3 Megan
dating_requests
request_id | member1 | member2 | request_time
----------------------------------------------------
1 1 2 2012-12-21 12:51:45
dating_alerts
alert_id | alerter_id | alertee_id | type | alert_time
-------------------------------------------------------
5 3 2 platonic 2012-12-21 10:25:32
dating_alerts_status
status_id | alert_id | alertee_id | viewed | viewed_time
-----------------------------------------------------------
4 5 2 0 0000-00-00 00:00:00
Sich vorstellen, dass Sie Karen und nur angemeldet haben, sollten Sie diese 2 Elemente:
1. Herb requested a date with you.
2. Megan wants a platonic relationship with you.
In einer Abfrage mit einer Obergrenze von 10. Stattdessen sind hier zwei Abfragen, die kombiniert werden müssen:
1. Herb requested a date with you.
-> query = "SELECT dr.request_id, dr.member1, dr.member2, m.member_name
FROM dating_requests dr
JOIN members m ON dr.member1=m.member_id
WHERE dr.member2=:loggedin_id
ORDER BY dr.request_time LIMIT 5";
2. Megan wants a platonic relationship with you.
-> query = "SELECT da.alert_id, da.alerter_id, da.alertee_id, da.type,
da.alert_time, m.member_name
FROM dating_alerts da
JOIN dating_alerts_status das ON da.alert_id=das.alert_id
AND da.alertee_id=das.alertee_id
JOIN members m ON da.alerter_id=m.member_id
WHERE da.alertee_id=:loggedin_id AND da.type='platonic'
AND das.viewed='0' AND das.viewed_time<da.alert_time
ORDER BY da.alert_time LIMIT 5";
Wieder, manchmal beide Tabellen leer sein, oder 1-Tabelle kann leer sein, oder beide voll (wo LIMIT 10 Tritte), geordnet nach der Zeit. Irgendwelche Ideen auf, wie man eine Abfrage zum ausführen dieser Aufgabe effizient? Gedanken, Tipps, Glockenspiel, Optimierungen sind willkommen.
- Wenn die Spalten zurückgegeben, die beiden Abfragen identisch sind, verbinden Sie diese mit
UNION
und machen die ganze Sache eine Unterabfrage eine äußere Abfrage ausführt, die dieLIMIT
. Sonst, Sie könnten bestimmen, die erforderlichenLIMIT
für die zweite Abfrage aus (10 minus die Anzahl der Datensätze, die von der ersten Abfrage zurückgegeben) - ist es wahrscheinlich am einfachsten, dies zu tun, in welcher Sprache Sie verwenden zum aufrufen Abfragen. - Erstellen Sie eine Tabelle mit Ihren erwarteten Ergebnissen. Du wirst sehen, das problem gibt.
- Es ist nicht möglich, kombinieren Sie 2 Abfragen mit verschiedenen Auswahllisten.
- die zurückgegebenen Spalten sind unterschiedlich, so dass die Regeln der UNION. Die zweite option klingt besser (zu subtrahieren Sie die restlichen), aber ich möchte Sie zu mischen, damit das timing ist chronologisch. Es ist ein bisschen eine Herausforderung!
- Vielleicht können Sie einige Literale Werte in jeder
SELECT
um line-up der Spalten, so dass Sie verwenden könnenUNION
? Sie müssen auch darüber nachdenken, wasORDER BY
Klausel zu verabschieden, so dass die Ergebnisse aus der ersten Tabelle nicht verdrängen die erwünschten Ergebnisse aus der zweiten. - Das klingt wie die beste Wahl so weit. Können Sie zeigen, wie würden Sie einzufügen Werte mit UNION? Eine Antwort mit code zum Beispiel würde es viel klarer für mich. Auch sollte es ein index auf der Zeit-tables für Optimierung hier oder wäre das langsame/überflüssig?
- Nach Einreichen meiner Antwort unten, es scheint mir, dass vielleicht diese ganze situation könnte vermieden werden durch eine Normalisierung Ihrer Daten eine touch: haben Sie eine weitere Tabelle von
events
, dass die Datensätze sowohlrequests
undalerts
, dann kommen Sie, die mit den relevanten Daten als angemessen.
Du musst angemeldet sein, um einen Kommentar abzugeben.
Kombinieren Sie mehrere Abfragen mit
UNION
, aber nur, wenn die Abfragen die gleiche Anzahl von Spalten. Im Idealfall werden die Spalten sind die gleichen, nicht nur in Daten-Typ, sondern auch in Ihrer semantischen Bedeutung; jedoch, MySQL kümmert sich nicht um die Semantik und mit unterschiedlichen Datentypen vom casting bis zu etwas mehr generisch - also, wenn nötig, Sie könnte überlast die Spalten an, die unterschiedliche Bedeutungen haben, aus jeder Tabelle, dann zu bestimmen, welche Bedeutung angemessen ist, in Ihren höheren level-code (obwohl ich nicht empfehlen, es zu tun auf diese Weise).Wenn die Anzahl der Spalten unterschiedlich ist, oder wenn Sie wollen, um eine bessere/weniger überlastet Ausrichtung von Daten aus zwei Abfragen, können Sie dummy-literal Spalten in Ihre
SELECT
Aussagen. Zum Beispiel:Konnte man sogar einige Spalten reserviert für die erste Tabelle und die andere für die zweite Tabelle, so dass Sie
NULL
anderswo (aber denken Sie daran, dass die Spalte Namen stammen aus der ersten Abfrage, so möchten Sie vielleicht, um sicherzustellen, Sie sind alle mit dem Namen gibt):Könnten Sie versuchen, die Ausrichtung Ihrer zwei Abfragen in dieser Weise, dann ist die Kombination mit einem
UNION
Betreiber; durch die AnwendungLIMIT
zu denUNION
sind Sie in der Nähe zu erreichen Ihr Ziel:Die einzige Frage, die bleibt, ist, dass, wie oben dargestellt, 10 oder mehr Datensätze aus der ersten Tabelle wird der "push-out" werden alle Datensätze aus der zweiten. Allerdings können wir nutzen eine
ORDER BY
in der äußeren Abfrage, diese zu lösen.Alles zusammen:
Natürlich, jetzt ist es an Ihnen, zu entscheiden, welche Art von Zeile Sie zu tun haben, und Lesen Sie jeden Datensatz in der Ergebnismenge (schlage vor, Sie testen
request_id
- und/oderalert_id
fürNULL
Werte; alternativ könnte man eine zusätzliche Spalte, um die Ergebnisse, die ausdrücklich aus, die Tabelle jeden Datensatz entstanden, aber es sollte gleichwertig sein, vorausgesetzt, dieseid
SpaltenNOT NULL
).ORDER BY
in der äußeren Abfrage - lassen Sie mich wissen, wenn Sie können ' T es herausfinden.