2008-08-06 14 views
20

Ich versuche, die folgende Abfrage aus:Wie verkette ich ganze Ergebnismengen in MySQL?

SELECT A,B,C FROM table WHERE field LIKE 'query%' 
UNION 
SELECT A,B,C FROM table WHERE field LIKE '%query' 
UNION 
SELECT A,B,C FROM table WHERE field LIKE '%query%' 
GROUP BY B ORDER BY B ASC LIMIT 5 

, die zusammen, kindasorta stecken drei Abfragen ist. Die Ergebnismenge, die zurückkommt, spiegelt jedoch die Ergebnisse von Abfrage Nr. 3 VOR den Ergebnissen von Abfrage Nr. 1 (unerwünscht) wider.

Gibt es eine Möglichkeit, diese zu priorisieren, so dass Ergebnisse als alle für Abfrage # 1, dann alle für Abfrage # 2 dann alle für Abfrage # 3 kommen? Ich möchte das in PHP noch nicht machen (ganz zu schweigen von der Kontrolle über die Ergebnisse, die in der ersten Abfrage auftauchten und nicht in der zweiten erscheinen).

Antwort

16

sollten Sie vielleicht eine vierte Spalte einschließlich versuchen, unter Angabe der Tabelle es herkam, und dann bestellen und Gruppe durch:

SELECT A,B,C, "query 1" as origin FROM table WHERE field LIKE 'query%' 
UNION 
SELECT A,B,C, "query 2" as origin FROM table WHERE field LIKE '%query' 
UNION 
SELECT A,B,C, "query 3" as origin FROM table WHERE field LIKE '%query%' 
GROUP BY origin, B ORDER BY origin, B ASC LIMIT 5 
3

Können Sie es als subselect, so etwas wie

select * from (
    SELECT A,B,C FROM table WHERE field LIKE 'query%' 
    UNION 
    SELECT A,B,C FROM table WHERE field LIKE '%query' 
    UNION 
    SELECT A,B,C FROM table WHERE field LIKE '%query%' 
) ORDER BY B ASC LIMIT 5 
0

Wenn es nicht eine Art, die sinnvoll, sie zu bestellen ist wünschen Sie, nicht Vereinigung die zusammen Ergebnisse - Rückkehr nur 3 separate Cord-Sets und behandeln Sie diese entsprechend in Ihrer Datenebene.

6

eine zusätzliche Spalte mit hartcodierte Werte hinzufügen, die Sie den gesamten resultset verwenden zu sortieren, etwa so:

SELECT A,B,C,1 as [order] FROM table WHERE field LIKE 'query%' 
UNION 
SELECT A,B,C,2 as [order] FROM table WHERE field LIKE '%query' 
UNION 
SELECT A,B,C,3 as [order] FROM table WHERE field LIKE '%query%' 
GROUP BY B ORDER BY [order] ASC, B ASC LIMIT 5 
0

ich schließlich (bei allen Vorschlägen suchen) kam zu dieser Lösung, es ist ein bisschen ein Kompromiss zwischen dem, was ich brauche und Zeit.

SELECT * FROM 
    (SELECT A, B, C, "1" FROM table WHERE B LIKE 'query%' LIMIT 3 
    UNION 
    SELECT A, B, C, "2" FROM table WHERE B LIKE '%query%' LIMIT 5) 
AS RS 
GROUP BY B 
ORDER BY 1 DESC 

es liefert 5 Ergebnisse insgesamt, sortiert aus der vierten "Spalte" und gibt mir, was ich brauche; eine natürliche Ergebnismenge (es kommt über AJAX) und ein Wildcard-Ergebnissatz, der unmittelbar danach folgt.

:)

/mp

1

select distinct a, b, c aus ( SELECT A, B, C, 1, wie O aus Tabelle WHERE Feld LIKE 'query%' UNION SELECT A , B, C, 2, wie O aus Tabelle WHERE Feld LIKE '% query' UNION SELECT A, B, C, 3 als O aus Tabelle WHERE Feld LIKE '% query%' ) ORDER BY o ASC LIMIT 5

Wäre meine Art es zu tun. Ich weiß nicht, wie das skaliert.

Ich verstehe nicht, die

GROUP BY B ORDER BY B ASC LIMIT 5 

Ist nur auf die letzte SELECT in der Union sie anwenden?

Ermöglicht es Ihnen MySQL tatsächlich, nach einer Spalte zu gruppieren und Aggregate in den anderen Spalten immer noch nicht zu tun?

EDIT: aaahh. Ich sehe, dass MySQL tatsächlich tut. Es ist eine spezielle Version von DISTINCT (b) oder etwas. Ich möchte nicht versuchen, ein Experte auf diesem Gebiet zu sein :)

0

Es gibt zwei Varianten von UNION.

'UNION' and 'UNION ALL' 

In den meisten Fällen, was Sie wirklich sagen möchte, ist UNION ALL, da es keine doppelten Beseitigung macht (Denken SELECT DISTINCT) zwischen den Sätzen, die in ziemlich viel Einsparungen hinsichtlich der Ausführungszeit führen kann.

Andere haben mehrere Ergebnissätze vorgeschlagen, was eine praktikable Lösung ist, aber ich würde davor warnen in zeitkritischen Anwendungen oder Anwendungen, die über WANs verbunden sind, da dies zu wesentlich mehr Roundtrips zwischen Server und Client führen kann.