Mysql
 sql >> Datenbank >  >> RDS >> Mysql

Gibt es eine Möglichkeit, eine WHERE-Klausel nur für ein Feld in MySQL anzuzeigen?

Vor MySQL 5.7 war die Standardeinstellung, nicht FULL group by zuzulassen . Das bedeutet, dass Sie eine Gruppierung nach haben können (die Aggregatfunktionen wie sum verwendet und max und count und group_concat ) mit anderen nicht aggregierten Spalten (nennen wir sie NON AGGS). ) wie Ihre ersten 3 angezeigten nicht alle Teil Ihrer group by Klausel. Es erlaubte es, aber die Ergebnisse würden normalerweise so aussehen:

  • Es hat super funktioniert, weil Sie Ihre Daten gut kennen und versuchen, einen Unterschied zu machen

  • Es hat schrecklich geklappt, weil es ein Snafu war

Vor 5.7 ONLY_FULL_GROUP_BY existierte, war aber standardmäßig deaktiviert.

In MySQL 5.7 kommt also der ONLY_FULL_GROUP_BY standardmäßig EIN. Als solches versuchen Sie eine Gruppierung nach, aber mit nicht allen die NON AGGS in group by -Klausel erhalten Sie einen Fehler.

Betrachten Sie das folgende Problem in 5.6 unten:

create table thing
(   col1 int not null,
    col2 int not null,
    age int not null
);
insert thing(col1,col2,age) values 
(1,2,10),
(1,3,20),
(2,3,20),
(2,2,10);

select col1,col2,max(age) from thing group by col1;
+------+------+----------+
| col1 | col2 | max(age) |
+------+------+----------+
|    1 |    2 |       20 |
|    2 |    3 |       20 |
+------+------+----------+

Was oben passiert, sind nicht alle NON AGGS befinden sich in group by . Es gibt das Maximum (Alter) von col1 zurück. Aber seit col2 war nicht in group by , es hat den Cluster-Index oder die physische Reihenfolge verwendet und ihm, vielleicht versehentlich (ein Fehler, ein Fehler), den falschen Wert für col2 gebracht. Abhängig von Ihren Absichten oder wenn Sie Ihre Daten kennen oder sich sogar darum kümmern. Dem Motor war es egal; vielleicht ja.

Um diese häufigen Fehler oder versehentliche Datenrückgabe zu vermeiden, aktiviert MySQL 5.7 ONLY_FULL_GROUP_BY standardmäßig.

In Ihrem Fall bilden die falschen Zeilen vermutlich Ihre Ergebnisse für die Spalten 2 und 3.

Siehe die Handbuchseite mit dem Titel MySQL-Behandlung von GROUP BY .

Beispiel 2

-- drop table if exists person;
create table person
(   id int auto_increment primary key,
    firstName varchar(100) not null,
    lastName varchar(100) not null
);

-- drop table if exists fruitConsumed;
create table fruitConsumed
(   id int auto_increment primary key,
    theDate date not null,
    fruitId int not null, -- does not really matter. Say, 1=apple, 2=orange from some other table
    personId int not null,
    qty int not null
);

-- truncate table person;
insert person (firstName,lastName) values 
('Dirk','Peters'),
('Dirk','Smith'),
('Jane','Billings');

-- truncate table fruitConsumed;
insert fruitConsumed (theDate,fruitId,personId,qty) values
('2016-10-31',1,1,2),
('2016-10-31',2,1,5),
('2016-10-31',2,2,12),
('2016-11-02',2,2,3);

Abfrage:

select p.firstName,p.lastName,sum(fc.qty) 
from person p 
join fruitConsumed fc 
on fc.personId=p.id 
group by p.firstName,p.lastName; 
+-----------+----------+-------------+
| firstName | lastName | sum(fc.qty) |
+-----------+----------+-------------+
| Dirk      | Peters   |           7 |
| Dirk      | Smith    |          15 |
+-----------+----------+-------------+

Das obige funktioniert hervorragend auf MySQL 5.6 und 5.7, unabhängig von der Einstellung für ONLY_FULL_GROUP_BY

jetzt betrachten

select p.firstName,p.lastName,sum(fc.qty) 
from person p 
join fruitConsumed fc 
on fc.personId=p.id 
group by p.firstName; 

+-----------+----------+-------------+
| firstName | lastName | sum(fc.qty) |
+-----------+----------+-------------+
| Dirk      | Peters   |          22 |
+-----------+----------+-------------+

Das obige ist oft auf MySQL 5.6 ohne ONLY_FULL_GROUP_BY akzeptabel aktiviert und schlägt bei 5.7 mit ONLY_FULL_GROUP_BY fehl aktiviert (Fehler 1055). Die obige Ausgabe ist im Grunde Kauderwelsch. Aber unten wird es etwas erklärt:

Wir wissen, dass Dirk, ein Dirk, nur ein Dirk, der einzige ist, der die innere Verbindung überlebt. Es gibt 2 Dirks. Aber wegen der group by p.firstName , bleibt uns nur noch ein Dirk. Wir brauchen einen lastName . Aufgrund der Nichtkonformität zum
SQL-Standard kann MySQL dies mit ONLY_FULL_GROUP_BY zulassen ausgeschaltet. Es wählt also einfach einen beliebigen alten Nachnamen aus. Nun, das erste, das es findet, und das ist entweder im Cache oder in der physischen Reihenfolge.

Und es ging mit Peters. Die Fruchtzählsumme gilt für alle Dirks.

Wenn Sie also so codieren, wird der nicht konforme Nicht-ONLY_FULL_GROUP_BY gibt Ihnen Kauderwelsch.

Und wie bereits erwähnt, erlaubt MySQL 5.7 dies standardmäßig nicht. Aber es kann auf die alte Weise angepasst werden, wenn Sie möchten.

Es wird dringend empfohlen, dass Sie Ihre Abfragen korrigieren und ONLY_FULL_GROUP_BY verlassen als aktiviert.