MySQL: UNION ignoriert ORDER BY - Was kann ich tun?

5 Antworten

Eine einfach zu durchschauende Möglichkeit zum Beeinflussen der Sortierung bei der Verwendung von UNION besteht darin, bei jedem SELECT eine Konstante voranzustellen. Wenn der erste SELECT z.B. eine 1, der zweite eine 2 bekommt und man sortiert vorrangig nach der Konstanten, so kommen alle Sätze des ersten SELECT nach vorne, die des zweiten nach hinten, egal was in den Sätzen steht.

Die ORDER BY -Anweisung darf nur einmal am Schluss stehen und darf nur Spalten-Nrn enthalten, da die Feldnamen bei den einzelnen SELECTs nicht zwangsläufig übereinstimmen müssen. Wenn Du also schreibst

ORDER BY 1, 7

so wird zuerst nach der vorangestellten Konstante und dann nach der 7. Spalte sortiert (die Spalte, wo Dein Sortierkriterium steht, die Konstante vorne natürlich mitgerechnet). Die Konstante muss nicht unbedingt vorne stehen. Es kann sein, dass der Stern Probleme macht und qualifiziert werden muss:

SELECT 1, location_task.*, job.* FROM location_task, job ....

UNION

SELECT 2, location_task.*, job.* FROM location_task, job ....

So geht es auf jeden Fall.

Jetzt musst Du noch die WHERE-Bedingungen so setzen, dass jeder SELECT die Sätze für die zugedachte Reihenfolge bekommt und dass keine Sätze mehrfach selektiert werden.

Ich habe öfter solche Abfragen und man bekommt so die raffiniertesten Reihenfolgen hin.

mein vorschlag:

select (jobid = 4) as job4, jobid, etc

FROM location_task, job WHERE location_task_location_id = 0 AND location_task_job = job_id

order by job4 desc, jobid

dann hast du lediglich ein neues feld job4 im datenarray, was du auf php-ebene einfach ignorierst.
(etc sind deine restlichen felder)

Perfekt. Funktioniert wie es soll. Danke :)

Hab die Lösung mal etwas angepasst:

SELECT *, (job_id = 4) AS job_id_selected
FROM location_task, job
WHERE location_task_location_id = 0
AND location_task_job = job_id
ORDER BY job_id_selected DESC, job_level ASC
0

Union macht aus zwei Datensätzen einen großen. Es ist kein "zusammenkleben" von Tabellenzeilen, sondern eine echte Fusion auf Inhaltsebene. Deshalb ist für ein Union-Statement auch nur ein einziges "order by" ganz am Ende zulässig. Die einzelnen Selects dürfen nicht sortieren.

Um die Sortierung so hinzubiegen, dass "4" vor "0" kommt, kannst du ein Case-Statement verwenden und die "4" auf "-99" abbilden:

https://dev.mysql.com/doc/refman/5.0/en/case.html

SELECT * FROM
(
SELECT
CASE job_id WHEN 4 THEN -99 ELSE job_id END CASE as SORT_JOB_ID,
location_task.*, job.*
FROM location_task, job
WHERE location_task_location_id = 0
AND location_task_job = job_id
)
ORDER BY SORT_JOB_ID

Klingt gut. Ich bekomme aber leider noch einen Error:

#1064 - You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'CASE as SORT_JOB_ID,
location_task.*, job.*
FROM location_task, job
WHERE locati' at line 7

0
@Revilon

Jetzt musst du im Handbuch deiner MySQL-Version nachschlagen. Wahrscheinlich mag er das "as" nicht, probier es mal ohne.

0
@halbsowichtig

Oh. Jetzt verstehe ich auch, was genau du vor hast. Leider geht das nicht, da die Daten in php verarbeitet werden und leider nicht verfälscht werden dürfen :/

0
@Revilon

Da wird auch nichts verfälscht. Das Sortierfeld wird zusätzlich selektiert, neben den normalen Feldern. Dein PHP-Skript muss es nicht mit ausgeben.

0

Das order by muss ausserhalb der Klammer für das select stehen

SELECT * FROM location_task, job WHERE location_task_location_id = 0 AND location_task_job = job_id UNION (SELECT * FROM location_task, job WHERE location_task_location_id = 0 AND location_task_job = job_id AND job_id != 4) ORDER BY job_level;

Sorry hab überlesen dass alle mit Job id 4 als erstes gezeigt werden sollen.

1
@PapaApe

Kein Problem. Vielleicht fällt dir noch was anderes ein. Wäre super :)

0

Musst du nicht im ersten Select noch ein

AND job_id = 4

anhängen?

Hatte ich beim kopieren irgendwie gelöscht. Hatte ich aber mit benutzt. Ändert nichts an der Tatsache ;)

0

Was möchtest Du wissen?