2016-05-07 11 views
8

Derzeit arbeite ich mit MySQL 5.7 in der Entwicklung und 5.6 in der Produktion. Jedes Mal, wenn ich eine Abfrage mit einer Gruppe von in der Entwicklung ausführen bekomme ich einen Fehler wie "Fehlercode: 1055. Ausdruck # 1 der SELECT-Liste ist nicht in GROUP BY"Gibt es für mysql 5.6 eine ANY_VALUE-Funktion?

Hier ist die Abfrage.

SELECT c.id, c.name, i.* 
FROM countries c, images i 
WHERE i.country_id = c.id 
GROUP BY c.id; Fixed for 5.7; 

SELECT c.id, c.name, 
     ANY_VALUE(i.url) url, 
     ANY_VALUE(i.lat) lat, 
     ANY_VALUE(i.lng) lng 
    FROM countries c, images i 
WHERE i.country_id = c.id 
GROUP BY c.id; 

Zur Lösung, dass ich die MySQL-Funktion von 5,7 ANY_VALUE verwenden, aber das Hauptproblem ist, dass sie nicht in MySQL 5.6

Also, wenn ich die SQL-Anweisung für die Entwicklung beheben i einen Fehler in Produktion.

Kennen Sie eine Lösung oder Polifill für die Funktion ANY_VALUE in MySQL 5.6?

+1

Warum nicht einfach 'MIN' oder' MAX' verwenden? – trincot

Antwort

9

Sie missbrauchen die notorious nonstandard MySQL extension to GROUP BY. Standard-SQL lehnt Ihre Abfrage immer ab, weil Sie Spalten angeben, die keine Aggregate sind und in GROUP BY nicht erwähnt werden.In Ihrem Dev-System versuchen Sie, das mit ANY_VALUE() zu umgehen.

SET @mode := @@SESSION.sql_mode; 
    SET SESSION sql_mode = ''; 
    /* your query here */ 
    SET SESSION sql_mode = @mode; 

Dies ermöglicht MySQL Ihre Anfrage zu akzeptieren:

In der Produktion können Sie die ONLY_FULL_GROUP_BY MySQL Mode. Versuchen Sie, this auszuschalten.

Aber schauen Sie, Ihre Abfrage ist nicht wirklich richtig. Wenn Sie es zum Ausführen überreden können, wird eine zufällig ausgewählte Zeile aus der Tabelle images zurückgegeben. Diese Art von Unbestimmtheit führt häufig zu Verwirrung bei Benutzern und Ihrem technischen Support.

Warum nicht die Abfrage besser machen, also wählt sie ein bestimmtes Bild aus. Wenn Ihre images Tabelle eine Autoinkrement id Spalte hat, können Sie dies tun, um das "erste" Bild auszuwählen.

SELECT c.id, c.name, i.* 
    FROM countries c 
    LEFT JOIN (
     SELECT MIN(id) id, country_id 
     FROM images 
     GROUP BY country_id 
     ) first ON c.id = first.country_id 
    LEFT JOIN images i ON first.id = i.id 

Das wird eine Zeile pro Land mit einem vorhersehbaren Bild angezeigt.

+0

pd: ich hasse Subselects! sind sie nicht langsamer? – Tim

+1

Ich denke, mit * subselect * meinen Sie eine Verbindung zu einem Aggregat wie ich. Meiner Erfahrung nach wird ihre Leistung, wie auch die Leistung anderer Abfragen, durch die Wahl der Indizes und anderer solcher Dinge bestimmt. Die eine, die ich gezeigt habe, kann eine Abfrage erheblich beschleunigen. Es reduziert die Anzahl der zu berücksichtigenden Zeilen. Und die Aggregatabfrage kann den erstaunlich effizienten losen Indexscan verwenden, um seine Sache zu machen. Lesen Sie darüber. –

7

Anstelle von ANY_VALUE können Sie die Aggregatfunktionen MIN oder MAX verwenden.

Alternativ können Sie den SQL-Modus ONLY_FULL_GROUP_BY, der standardmäßig für MySql 5.7 festgelegt ist, nicht festlegen und ist verantwortlich für den Unterschied, den Sie mit MySql 5.6 haben. Dann können Sie die Aktualisierung Ihrer Abfragen verzögern, bis Sie alle Ihre Umgebungen auf MySql 5.7 migriert haben.

Welche der beiden ist die bessere Option, ist umstritten, aber auf lange Sicht wird es besser sein, Ihre Abfragen anzupassen, so dass sie die ONLY_FULL_GROUP_BY Regel einhalten. Die Verwendung von MIN oder MAX kann dabei sicherlich nützlich sein.

+0

Vielen Dank für Ihre Zeit und Antwort, von der Wat, ANY_VALUE Referenz http://dev.mysql.com/doc/refman/5.7/en/miscellent-functions.html#function_any-value – Tim

+0

In meinem Fall mit MAX anstelle von ANY_VALUE hat erlaubt, dass meine Abfrage für MySQL 5.5 funktioniert. und 5.7. Danke für den Vorschlag. –

3

Seit Jahrzehnten Sie Abfragen schreiben könnten, die

Im Standard-SQL nicht gültig in Standard-SQL, aber absolut gültigen mysql waren, eine Abfrage, die ein GROUP BY-Klausel enthält nicht zu nicht aggregierten Spalten in der Auswahlliste verweisen, dass sind nicht in der GROUP BY-Klausel benannt. Zum Beispiel ist diese Abfrage illegal in Standard-SQL- , weil die nicht aggregierten Namensspalte in der Auswahlliste nicht erscheinen in der GROUP BY:

SELECT o.custid, c.name, MAX (o.payment) FROM Aufträge AS o, Kunden AS c WO o.custid = c.custid GROUP BY o.custid; Für die Abfrage auf legal sein, muss die Spalte Name aus der Auswahlliste oder in der GROUP BY-Klausel weggelassen werden.

MySQL erweitert die Standard-SQL-Verwendung von GROUP BY, sodass die Auswahlliste auf nicht aggregierte Spalten verweisen kann, die nicht in der GROUP BY-Klausel benannt sind.

Dies kommt von der Mysql 5.6 Handbuch Seite GROUP BY. Wenn Sie auf dieselbe Seite für 5.7.6 schauen, sehen Sie, dass sich die Dinge geändert haben. Und hat sich dramatisch verändert !!

Diese Seite gibt Ihnen auch die Lösung. Deaktivieren Sie ONLY_FULL_GROUP_BY Das wird es Ihrer alten 5.6-Abfrage ermöglichen, auf 5.7.6 zu funktionieren (entfernen Sie ANY_VALUE aus Ihrer Abfrage, da es in 5.7.6 nicht verfügbar ist, aber verwenden Sie stattdessen die ONLY_FULL_GROUP_BY).

+1

Danke für Ihre Zeit und antworten. – Tim

Verwandte Themen