MySQL - Auswahl einer Spalte, die nicht in Group By
Ich versuche zum hinzufügen von Funktionen zu einer vorhandenen Anwendung, und ich kam in eine MySQL-Ansicht, so etwas wie dieses:
SELECT
AVG(table_name.col1),
AVG(table_name.col2),
AVG(table_name.col3),
table_name.personID,
table_name.col4
FROM table_name
GROUP BY table_name.personID;
OK also es gibt ein paar Aggregatfunktionen. Sie können wählen, personID, weil Sie die Gruppierung, indem Sie es. Aber es ist auch die Auswahl einer Spalte, die nicht in einer Aggregatfunktion und nicht Teil der GROUP BY-Klausel. Wie ist das möglich??? Ist es einfach, wählen Sie eine zufällige Wert, da die Werte definitiv nicht eindeutig pro Gruppe?
Wo ich herkomme (MSSQL-Server), das ist ein Fehler. Kann mir jemand erklären, dieses Verhalten zu mir und warum ist es erlaubt in MySQL?
InformationsquelleAutor colithium | 2009-06-21
Du musst angemeldet sein, um einen Kommentar abzugeben.
Es ist wahr, dass dieses feature ermöglicht einige mehrdeutige Abfragen, und im hintergrund gibt ein ResultSet zurück, wird ein beliebiger Wert ausgewählt aus dieser Spalte. In der Praxis, es neigt dazu, den Wert aus der Zeile, in der Gruppe, die physisch gespeichert ersten.
Diese Abfragen sind nicht mehrdeutig, wenn Sie nur die Spalten auswählen, die funktional abhängig von der Spalte(N) in der GROUP BY-Kriterien. In anderen Worten, wenn es kann nur einen eindeutigen Wert von der "Doppeldeutige" - Spalte pro Wert definiert die Gruppe, es gibt kein problem. Diese Abfrage wäre illegal in Microsoft SQL Server (und ANSI-SQL), obwohl es logisch nicht führen Mehrdeutigkeit:
Außerdem hat MySQL eine SQL-Modus, um es Verhalten sich nach der standard:
ONLY_FULL_GROUP_BY
FWIW, SQLite erlaubt auch diese mehrdeutige GROUP BY-Klauseln, aber es wählt den Wert aus der letzten Zeile in der Gruppe.†
† zumindest in der version, die ich getestet. Was es bedeutet, zu sein beliebigen ist, dass entweder MySQL oder SQLite ändern könnte, deren Umsetzung in der Zukunft, und haben einige sich anders Verhalten. Sie sollten deshalb nicht ausschließlich auf das Verhalten bleiben, wie es derzeit in unklaren Fällen wie diesem. Es ist besser zu umschreiben, Ihre Anfragen werden deterministische und nicht mehrdeutig. Das ist, warum MySQL 5.7 jetzt ONLY_FULL_GROUP_BY aktiviert standardmäßig.
vielen Dank, Sie sind richtig. MySQL 5.7 wurde verbessert, und es ist viel intelligenter, in diesem Fall der Unterstützung von ANSI SQL.
Hier ist auch ein Artikel, der beschreibt, dass die Ausgabe: percona.com/blog/2006/09/06/...
InformationsquelleAutor Bill Karwin
Sollte ich Googelte ein wenig länger... Es scheint, ich fand meine Antwort.
Immer noch, dass scheint nur... falsch.
Es ist nicht mehr "falsch" als
SELECT * FROM table1
Ergebnisse zurück, die in einer bestimmten, konsistenten Reihenfolge: es ist ein feature, kein bug.Das ist eindeutig "falsch" (noch schlimmer:)). SQL definiert zu werden, eine set-basierte Sprache und die Reihenfolge der Elemente in einer Menge ist irrelevant. Die
SELECT * FROM table1
gibt den gleichen Satz von Datensätzen, solange die Datensätze der Tabelle nicht ändern. Durch Kontrast, die eine Gruppierte Abfrage verschiedene Datensätze, je nach der Reihenfolge, wie die Datensätze in die Tabelle eingefügt wurden. Das ist definitiv falsch. Ähnlich wie viele andere Dinge im Zusammenhang mit mysql, das ist eine gefährliche gotcha mysql versucht zu verkaufen, als ein "feature".InformationsquelleAutor colithium
Es muss nicht, aber es Art erklärt, was passiert. Der obige code ist ein Beispiel, wie diese nicht-standard-Verhalten kann modelliert werden mit standard-SQL.
InformationsquelleAutor Salih Kiraz
Lassen Sie uns sagen, Sie haben eine Abfrage wie diese:
In diesem Fall für jeden möglichen Wert für
g
, mysql wählt eine der entsprechenden Werte vonv
.Aber, was man gewählt wird, hängt von einigen Umständen ab.
Ich habe irgendwo gelesen, dass für jede Gruppe g, wird der erste Wert
v
gehalten wird, in der Reihenfolge, wie die Datensätze in die Tabelle eingefügt wurdent
.Dies ist ziemlich hässlich, da die Datensätze in einer Tabelle behandelt werden soll als ein set, wo die Reihenfolge der Elemente nicht von Bedeutung. Das ist so "mysql-ish"...
Wenn Sie möchten, um zu bestimmen, welcher Wert für
v
zu halten, müssen Sie einen Antrag einer untergeordneten select-Anweisung fürt
wie diese:Diese Weise definieren Sie, in welcher Reihenfolge die Datensätze der Unterabfrage verarbeitet werden, indem die externe Abfrage, damit Sie Vertrauen können, welchen Wert der
v
es Holen für die einzelnen Werte derg
.Allerdings, wenn Sie brauchen etwas, WO die Bedingungen dann sehr vorsichtig sein. Wenn Sie fügen der WHERE-Bedingung der Unterabfrage dann hält es das Verhalten, es wird immer wieder der Wert, den Sie erwarten:
Dies ist, was Sie erwarten, die untergeordnete select-Filter und sortiert die Tabelle. Es hält die Datensätze, in denen
g
hat den angegebenen Wert und die externe Abfrage, dieg
und der erste Wert fürv
.Jedoch, wenn Sie hinzufügen, die gleiche WHERE-Bedingung der äußeren Abfrage, dann bekommst du eine nicht-deterministische Ergebnis:
Überraschend ist, erhalten Sie möglicherweise unterschiedliche Werte für
v
bei der Ausführung die gleiche Abfrage wieder und wieder... seltsam. Das erwartete Verhalten ist, um alle Datensätze in der entsprechenden Reihenfolge aus der Unterabfrage filtern Sie in der äußeren Abfrage und dann Kommissionierung die gleiche, wie es nahm in den vorherigen Beispiel. Aber es funktioniert nicht.Wählt er einen Wert für
v
scheinbar zufällig. Die gleiche Abfrage unterschiedliche Werte fürv
wenn ich ausgeführt mehr (~20), manchmal aber die Verteilung war nicht einheitlich.Wenn anstelle der Zugabe eine äußere, WO Sie angeben, eine Bedingung wie diese:
Dann bekommen Sie ein konsequentes Verhalten wieder.
FAZIT: ich würde vorschlagen, sich nicht darauf zu verlassen, die auf dieser Technik überhaupt. Wenn Sie wirklich wollen/müssen, um dann zu vermeiden, wenn die Verhältnisse in der äußeren Abfrage. Verwenden Sie es in der inneren Abfrage, ob Sie oder einer HAVING-Klausel in der äußeren Abfrage.
Getestet habe ich es mit diesen Daten:
in mysql 5.6.41.
Vielleicht ist es nur ein bug, der bekommt/bekam behoben in neueren Versionen, bitte geben Sie feedback, wenn Sie haben Erfahrung mit neueren Versionen.
InformationsquelleAutor Csongor Halmai