sql >> Databasteknik >  >> RDS >> Mysql

Finns det något sätt att visa en WHERE-sats bara för ett fält i MySQL?

Före MySQL 5.7 var standarden att tillåta icke FULL group by . Vilket betyder att du kan ha en grupp efter (som använder aggregerade funktioner som sum och max och count och group_concat ) med andra icke aggregerade kolumner (låt oss kalla dem NON AGGS ) gillar dina första 3 visade inte alla en del av din group by klausul. Det tillät det men resultaten skulle vanligtvis se ut så här:

  • Det fungerade utmärkt eftersom du känner till din data väl och försöker uppnå en distinkt

  • Det gick hemskt eftersom det var ett smyg

Före 5.7, ONLY_FULL_GROUP_BY existerade men den var avstängd som standard.

Så i MySQL 5.7 kommer ONLY_FULL_GROUP_BY förinställd PÅ. Som sådan om du försöker en grupp av, men med inte alla NON AGGS i group by klausul skulle du få ett fel.

Tänk på följande problem i 5.6 nedan:

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 |
+------+------+----------+

Det som händer ovan är inte alla NON AGGS finns i group by . Den returnerar max(åldern) med kol1. Men eftersom col2 fanns inte i group by , använde den Cluster Index eller Physical Ordering och gav det, kanske oavsiktligt (en snafu, ett misstag), fel värde för col2. Beroende på dina avsikter eller att känna till dina data eller till och med bry sig. Motorn brydde sig inte; kanske du gör det.

För att undvika dessa vanliga misstag eller oavsiktlig dataretur, aktiverar MySQL 5.7 ONLY_FULL_GROUP_BY som standard.

I ditt fall utgör fel rader dina resultat förmodligen för kolumn 2 och 3.

Se manualsidan med titeln MySQL-hantering av GROUP BY .

Exempel 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);

Fråga:

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 |
+-----------+----------+-------------+

Ovanstående fungerar utmärkt på MySQL 5.6 och 5.7 oavsett inställningen för ONLY_FULL_GROUP_BY

överväg nu

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 |
+-----------+----------+-------------+

Ovanstående är ofta acceptabelt på MySQL 5.6 utan ONLY_FULL_GROUP_BY aktiverad och misslyckas på 5.7 med ONLY_FULL_GROUP_BY aktiverad (fel 1055). Ovanstående utdata är i grunden struntprat. Men nedan förklaras det något:

Vi vet att Dirk, en Dirk, bara en Dirk, är den ende som överlever den inre sammanfogningen. Det finns 2 Dirks. Men på grund av group by p.firstName , vi har bara en Dirk kvar. Vi behöver ett lastName . På grund av bristande överensstämmelse med
SQL-standarden kan MySQL tillåta detta med ONLY_FULL_GROUP_BY avstängd. Så den väljer bara vilket gammalt efternamn som helst. Tja, den första den hittar, och det är antingen i cachen eller den i den fysiska beställningen.

Och det gick med Peters. Frukträkningssumman är för alla Dirks.

Så om du kodar så här, den icke-överensstämmande icke-ONLY_FULL_GROUP_BY ger dig skratt.

Och som sagt, MySQL 5.7 levererade som standard att inte tillåta detta. Men det går att justera till det gamla sättet om du vill.

Vi rekommenderar starkt att du fixar dina frågor och lämnar ONLY_FULL_GROUP_BY som aktiverat.



  1. Implementera kommentarer och likes i databasen

  2. Behöver Oracle SQL för att dela upp datum/tidsintervall efter dag

  3. SQL GROUP BY-klausul för nybörjare

  4. Konsolidera SQL Server-instanser genom klustring och stapling