Union All ohne Sortierung

Hi,

habe hier eine SQL-Abfrage, die mich gerne ärgert und über mich lacht. Das zurückgegebene Ergebnis der Abfrage sortiert sich einfach von selbst, was es aber nicht tun soll:

select distinct * from
(SELECT name,gemeinde, astext(referenz_900913) as punkt,astext(extent_900913) as extent,astext(geom_900913) as geom 
FROM gc_berechnet 
WHERE name ILIKE 'hallo%'  

UNION ALL


 (SELECT name,gemeinde, astext(referenz_900913) as punkt, astext(extent_900913) as extent,astext(geom_900913) as geom
FROM gc_berechnet 
WHERE name ILIKE '%$hallo%'))a

Eine Sortierung ist aber nicht gewünscht. Ergebnis der ersten Unterabfrage mit …ILIKE ‘hallo%’ soll einfach nur mit dem Ergebnis der zweiten Unterabfrage vereint werden, sodass das die Ausgabe bspw. so aussieht:
hallo1
hallo3
ahallo
bhallo

und nicht
ahallo
bhallo
hallo1
hallo3


Wie kann ich das am besten realisieren ?
(Ich dachte, UNION ALL vernachlässige Sortierung, was es aber hier nicht der Fall ist.)



Besten Dank schon mal!!
Grüße
m.sirin

//EDIT: liegt wohl an dem Distinct… sobald es draußen ist, gibt es keine Sortierung, dafür aber doppelte Einträg.Auch nicht gut…

UNION vs. UNION ALL hat nichts mit Sortierung zu tun. UNION entfernt einfach Duplikate aus dem Ergebnis währen UNION ALL das nicht tut.

In älteren Postgres Versionen wurde das Entfernen der Duplikate auch mal über sortieren gemacht (war aber ein Nebeneffekt) bei neueren Versionen geht das auch ohne Sortieren.

Ansonsten gilt: solange Du kein ORDER BY verwendest ist es der Datenbank freigestellt in welcher Reihenfolge die Datensätze zurückkommen!

Wenn Du eine bestimmte Reihenfolge erzwingen willst dann musst Du ORDER BY verwenden. Wenn Du das nicht verwendest darfst/kannst Du Dich auch nicht über die Reihenfolge beschweren.
Ohne ORDER BY darf die Reihenfolge auch bei jeder Abfrage anders sein. Hänge also ein ORDER BY an, und schon klappt das.

Genau die Nichtsortierung wollte ich ja auch haben, also den Rohzustand, wie ihn mir Postgres zurückliefert und nichts mit order by :slight_smile: .Okay, dann liegt es also nicht an union all, gut.
. Oh, soeben bemerke ich, dass durch das distinct wohl ein automatisches Order By Asc erzwungen wird…

Kann man die Sortierung des Distincts nicht abschalten^^ ?

Es gibt keinen “Rohzustand”!

Selbst wenn du die gleiche Tabelle mit verschiedenen Verbindungen liest, kann es passieren, dass du eine unterschiedliche Reihenfolge bekommst. Das liegt daran, dass sich alle weiteren Anfragen auf die erste Aufschalten und ab dem aktuellen Punkt “mitlesen”. Wenn die ersten Anfrage fertig ist, fangen die anderen von vorne an und arbeiten bloß noch das fehlende Stück ab. (Der Effekt wirkt sich aber erst ab größeren Tabellen aus.)

Du hast also nie eine voraussagbare Sortierung und wie castorp schon sagt: wenn du nichts verlangst, darfst du dich über das Ergebnis auch nicht beschweren.

Das gilt aber erst ab 8.2, oder?

Andreas

Ja. Das sollte nur verdeutlichen, dass es keinen “Rohzustand” gibt, wenn man keine Sortierung angibt.
Auch vor 8.2 kamen die Daten nach einer Änderung an einem Datensatz in einer veränderten Reihenfolge aus der DB. Da gab es halt nur keine parallelen Scans.

Das ist korrekt. Und ab 8.2 kann das sogar bei nicht geänderten Tabellen passieren, also noch viel schlimmer.

Andreas

okay :slight_smile:

ich will doch nur, dass die Ergebnisse der ersten Subquery über dem Ergebnis der zweiten Subquery erscheinen.
Notfalls ist meine 1.Subquery so : … name=‘hallo’; d.h. es gibt nur eine Zeile als Rückgabe.
Diese Rückgabe soll mit dem anderen Ergebnis unioniert werden, und dabei Ergebnisse nur einmal vorkommen lassen. Und das ist nicht möglich? :frowning:
Oder mit anderen Worten: Das relevanteste Ergebnis zum Suchstring soll möglichst weit oben erscheinen.

Du willst Volltextsuche! Ganz sicher.

Dann selektiere in der ersten Subquery eine extra Spalte mit dem Wert 1 und in der zweiten Subquery in dieser Spalte 2. Nach dieser Spalte sortierst Du dann, fertisch…


Andreas

okay, wenn ich das mit den Zahlen in der Extraspalte mache, bringt das zwar etwas, jedoch funktioniert dann Distinct bzw. Group By nicht mehr, d.h. doppelte Einträge werden angezeigt, was eigentlich auch einleuchtend ist, da es zwei verschiedene Zahlen sind, die man nicht zusammenfassen kann.

Sonst noch irgendwelche Vorschläge?

Ja. Wir gehen noch mal einen Schritt zurück und erinnern uns, was wir in der Schule, 2. Klasse, gelernt haben:

Datenbanken arbeiten mit Mengen von Objekten. Zum Beispiel den 100 Streichhölzern in einer Streichholzschachtel. Wenn Du diese auskippst (SELECT ohne ORDER BY), dann liegen die halt einfach so da. Einfach so. Unsortiert. Halt ohne ORDER BY.

Wenn Du die sortiert haben willst, z.B. nach Größe, Gewicht oder Menge an den roten Zeugs da vorne dran, dann mußt Du halt danach sortieren, von selbst wird das nix. Und wenn Du eine zufällige Sortierung willst: da kann Dir geholfen werden: ORDER BY RANDOM(). Aber ohne jegliche Angabe einer Sortierordnung ist es der DB (oder der Schwerkraft bei den Streichhölzern) freigestellt, wie die Daten (Streichhölzer) rauspurzeln. Dies kann, muß aber nicht, im Falle einer DB zufällig immer gleich sein. Darauf verlassen kann und sollte man sich nicht.

Andreas

Hallo :wink:

ich weiß der Beitrag ist schon etwas länger her, aber ich habe mich mit dem gleichen Problem beschäftigt und jetzt selbst eine Lösung gefunden.
Und da ich auch sonst nirgends etwas dazu gefunden habe möchte ich meine Lösung hier mit euch teilen ;D

Der Trick ist Recht einfach. Man fügt während der Abfrage jeder tabellen einen Wert als Gewichtung hinzu und sortiert dannach nach diesem.

Beispiel
Select Name, 1 AS Wert
FROM tbl1
Where Id = 1
UNION ALL
SELECT Name, 2 AS Wert
FROM tbl2
ORDER BY Wert, Name

und schon werden alle Namen der ersten Tabelle zuerst sortiert.

PS: srry für Rechtschreibfehler, dass Leben ist zu kurz um korrektur zu lesen