2012-05-09 7 views
5

Ich gehe durch den Schmerz der Normalisierung einer schrecklichen Legacy-Datenbank und habe entdeckt, was ich denke, ist ein Fehler mit dem DBMS.Sollte ein ORDER BY jemals die Anzahl der zurückgegebenen Zeilen einer SELECT-Abfrage beeinflussen?

Diese Abfrage gibt die Ergebnisse als ich erwarten:

SELECT DISTINCT RIGHT(SQUEEZE(thing_id), 2) AS thing_id, TRIM(thing_name) 
FROM thing 
ORDER BY thing_id, thing_name; 
(16 rows) 

Das erste Mal, dass ich die Abfrage lief, hatte ich versehentlich die falschen Spalten in der ORDER BY, wie unten verwendet:

SELECT DISTINCT RIGHT(SQUEEZE(thing_id), 2) AS thing_id, TRIM(thing_name) 
FROM thing 
ORDER BY thing_name, location; 
(33 rows) 

Beachten Sie, dass das einzige, was geändert werden muss, ORDER BY ist und die Anzahl der zurückgegebenen Zeilen von 16 auf 33 steigt. Die Ergebnisse, die es gibt, sind nicht DISTINCT, wie die Abfrage angibt.

Ich glaube, das ist ein offensichtlicher Fehler, aber ein Kollege sagt, dass es normal ist, denn wenn wir nach "Ort" bestellen, wird es unsichtbar in die Ergebnisse aufgenommen.

Sollte die ORDER BY jemals die Anzahl der in einer SELECT-Abfrage zurückgegebenen Zeilen beeinflussen?

EDIT: Ich hatte eine andere Person, um die Abfragen zu sehen, und ich kopierte die Abfragen in zwei separate Dateien, dann führte einen Diff-Befehl auf ihnen. Es ist zu 100% sicher, dass der einzige Unterschied zwischen den beiden Abfragen die in ORDER BY aufgelisteten Spalten sind.

UPDATE: Ingres haben seit Patch 14301 mit Bugfix veröffentlicht: "Bug 126640 (GENERIC) Abfrage mit Order-by-Ausdruck und distinkte Aggregat gibt mehr Zeilen als erwartet zurück. Die Spalten im Ausdruck Reihenfolge sind nicht in der Auswahlliste . "

Die fragliche Abfrage führt nun zu einem Fehler, da die Ergebnisse nicht korrekt sind.

+0

Welche DB ist das? –

+4

Tag sagt ingres – ilanco

+0

Konnten Sie die genaue Frage zeigen? –

Antwort

3

Da die Reihenfolge der Operationen in SQL ist:

FROM > WHERE > GROUP BY > HAVING > SELECT > ORDER BY 

dies scheint in der Tat ein Fehler zu sein. Welches DBMS ist das?

+0

Wie das Tag sagt, ist das DBMS Ingres. –

+1

Dank @Mario, wählte ich Ihre Antwort, weil Sie auch angegeben _why_ die ORDER BY sollte das Ergebnis so nicht beeinflussen. –

+0

@rusty_turkey danke. Ich würde auch gerne sagen, dass die einzigen zwei Klauseln, in denen Zeilen jemals aus dem Ergebnis entfernt werden können, 'where' und' having' sind, und vielleicht auch 'select', wenn Sie" distinct "angeben oder wenn die restlichen Spalten NULL haben Reihen. – MarioDS

3

Nein, order by sollte nicht die Anzahl der zurückgegebenen Zeilen beeinflussen.

Wenn das, was Sie sagen, wahr ist, wäre das ein sehr merkwürdiger und grundlegender Fehler. Ich würde verdreifachen (dann vervierfachen) überprüfen Sie die Rückkehr Spalten auf beiden Abfragen zu machen absolut sicher, dass dies nicht ein einfacher Benutzer Fehler vor dem E-Mailing der Ingres Jungs.

bearbeiten

Eigentlich würde ich auch versuchen, die Abfragen auf einer Backup-Datenbank ausgeführt wird. Wenn Sie keine Sicherungskopie zur Verfügung haben, können Sie möglicherweise die Datenbank kopieren, die Sie haben (falls Ingres dies unterstützt).

Ich hatte Abfragen, die unsinnige Ergebnisse auf Maschinen mit fehlerhafter Hardware zurückgaben. Das wird definitiv etwas sein, das du überprüfen willst.

+0

Ich überprüfte die Abfragen, als ich dachte, ich sei entweder verrückt oder nichts Neues über SQL.Wie bei der Bearbeitung meines ursprünglichen Beitrags habe ich auch die Abfragen in zwei Dateien kopiert und eingefügt und dann einen Unix-Vergleich vorgenommen, um sie zu bestätigen. –

+0

@rusty_turkey Siehe meine Bearbeitung –

6

Das Problem, das ich sehe, ist, dass die zweite Abfrage eine Spalte (location) in der ORDER BY hat, die nicht in der SELECT DISTINCT Liste enthalten ist. Eigentlich sind beide Abfragen ungültig SQL (trotzdem scheint Ingres ihnen zu erlauben).Ich vereinfacht sie (so der erste ist ok) zu:

Abfrage ein (gültig SQL):

SELECT DISTINCT 
     thing_id 
    , thing_name 
FROM thing 
ORDER BY thing_id 
     , thing_name ; 

Abfrage zwei (ungültige SQL sollten Fehler erzeugen):

SELECT DISTINCT 
     thing_id 
    , thing_name 
FROM thing 
ORDER BY thing_name 
     , location; 

Warum sollte es gibt Fehler? Denn die ORDER BY sollte nach SELECT und DISTINCT verarbeitet werden. So können zwei oder mehr Zeilen in der Originaltabelle dieselben haben thing_id und thing_name, aber unterschiedliche location. Diese Zeilen werden zu einem zusammengeführt. Daher wird kein Standortwert für die Bestellung verwendet. Selbst wenn es (einen versteckten Ort valiue) gab, welcher von den vielen sollte es sein?

SELECT DISTINCT Abfragen können mit SELECT ALL und GROUP BY (auch ungültig in diesem Fall) neu geschrieben werden:

SELECT ALL 
     thing_id 
    , thing_name 
FROM thing 
GROUP BY thing_id 
     , thing_name 
ORDER BY thing_name 
     , location; 

Die oben (Abfrage 2) funktioniert tatsächlich Fehler in PostgreSQL, SQL-Server und Oracle erzeugen. Testen Sie es in SQL-Fiddle


Von der falschen Anzahl der Zeilen, die von der zweiten Abfrage in Ingres zurück, denke ich, dass hinter den Kulissen, was passiert ist, dass er location heimlich in der SELECT Liste gehalten wird, so kann es verwendet werden, die ORDER BY und dann entfernt. Dies, in Kombination mit den DISTINCT Ergebnissen in dem Nicht-Standard-Buggy Verhalten:

SELECT DISTINCT 
     thing_id 
    , thing_name 
    (, location   --- hidden column) 
FROM thing 
ORDER BY thing_name 
     , location; 

Sie können es nennen entweder ein Bug oder ein Feature, spielt es keine Rolle, solange Sie sie wissen sollten wirklich nicht sein in erster Linie erlaubt.

Es scheint, dass ein ähnliches Problem vor einem Jahr in Actian Forum gemeldet wurde: Problem with DISTINCT + ORDER BY und angeblich behoben. Keine Ahnung, auf welche Version sie verweisen oder ob sie tatsächlich behoben wurde oder nicht (und was "fix" bedeutet).


Wenn Sie wollen, dass die Abfrage gültig zu sein und verhalten sich wie erwartet, könnten Sie diese somethign wie verwenden:

SELECT 
     RIGHT(SQUEEZE(thing_id), 2) AS squeezed_thing_id 
    , TRIM(thing_name)    AS trimmed_thing_name 
    , MIN(location)    AS a_location   --- or MAX() 
FROM 
    thing 
GROUP BY 
     RIGHT(SQUEEZE(thing_id), 2) 
    , TRIM(thing_name)  
ORDER BY 
     trimmed_thing_name 
    , a_location ;     
+1

Ich habe auf das Öffnen eines Lehrbuchs zurückgegriffen, und es besagt, dass ORDER BY Spalten angeben kann, die nicht im Ergebnis erscheinen, aber einige Dialekte bestehen darauf, dass ORDER BY nur auf Spalten verweisen kann, die im Ergebnis erscheinen. Also in diesem Fall Ingres erlauben es und die DBMS-Server, die Sie erwähnten, nicht. –

+0

In einer Abfrage ohne 'SELECT DISTINCT' und ohne' GROUP BY', ja, ich denke, fast alle (wenn nicht alle) DBMS erlauben jede Spalte in der 'ORDER BY' zu sein. Wenn es eine Gruppierung gibt, ist das sehr unterschiedlich. Und 'SELECT DISTINCT' ist eine Form der Gruppierung. –

0

Wenn Sie location zur ersten Abfrage hinzufügen, dann werden beide die gleiche Rück Anzahl der Reihen. Der Grund, warum die zweite Abfrage mehr Zeilen zurückgibt, liegt darin, dass Sie in dieser Abfrage nicht location auswählen. Wie bereits erwähnt, erlauben einige RDBMS es nicht, Ingres tut. Wahrscheinlich, weil der SQL-Standard es nicht verbietet?.