sql >> Database teknologi >  >> RDS >> Mysql

Er der en måde at vise en WHERE-klausul kun for et felt i MySQL?

Før MySQL 5.7 var standarden at tillade ikke FULD group by . Hvilket betyder, at du kan have en gruppe efter (der bruger aggregerede funktioner som sum og max og count og group_concat ) med andre ikke-aggregerede kolonner (lad os kalde dem NON AGGS ) synes godt om dine første 3 viste ikke alle en del af din group by klausul. Det tillod det, men resultaterne ville typisk virke sådan her:

  • Det fungerede godt, fordi du kender dine data godt og forsøger at opnå en distinkt

  • Det fungerede forfærdeligt, fordi det var et snavs

Før 5.7, ONLY_FULL_GROUP_BY eksisterede, men den var som standard slået FRA.

Så i MySQL 5.7 følger ONLY_FULL_GROUP_BY standard ON. Som sådan, hvis du forsøger en gruppe af, men med ikke alle NON AGGS i group by klausul, ville du få en fejl.

Overvej følgende problem i 5.6 nedenfor:

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, der sker ovenfor, er ikke alle NON AGGS er i group by . Det returnerer max(alder) ved col1. Men siden col2 var ikke i group by , den brugte Cluster Index eller Physical Ordering og bragte det, måske utilsigtet (en snafu, en fejl), den forkerte værdi for col2. Afhængig af dine intentioner eller kendskab til dine data eller endda omsorg. Motoren var ligeglad; måske gør du det.

For at undgå disse almindelige fejl eller utilsigtet dataretur, aktiverer MySQL 5.7 ONLY_FULL_GROUP_BY som standard.

I dit tilfælde udgør de forkerte rækker dine resultater, formentlig for kolonne 2 og 3.

Se manualsiden med titlen MySQL-håndtering af GROUP BY .

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

Forespørgsel:

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

Ovenstående fungerer godt på MySQL 5.6 og 5.7 uanset indstillingen for ONLY_FULL_GROUP_BY

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

Ovenstående er ofte acceptabelt på MySQL 5.6 uden ONLY_FULL_GROUP_BY aktiveret og fejler i 5.7 med ONLY_FULL_GROUP_BY aktiveret (fejl 1055). Ovenstående output er dybest set volapyk. Men nedenfor er det forklaret lidt:

Vi ved, at Dirk, en Dirk, bare en Dirk, er den eneste, der overlever den indre sammenføjning. Der er 2 Dirks. Men på grund af group by p.firstName , står vi tilbage med kun én Dirk. Vi har brug for et lastName . På grund af manglende overensstemmelse med
SQL-standarden kan MySQL tillade dette med ONLY_FULL_GROUP_BY slukket. Så den vælger bare et hvilket som helst gammelt efternavn. Nå, den første den finder, og det er enten i cachen eller den i den fysiske bestilling.

Og det gik med Peters. Frugttællingssummen er for alle Dirks.

Så hvis du koder sådan, vil den ikke-overensstemmende ikke-ONLY_FULL_GROUP_BY giver dig volapyk.

Og som sagt, MySQL 5.7-skibe tillod som standard ikke dette. Men det kan justeres til den gamle måde, hvis du vælger det.

Det anbefales stærkt, at du løser dine forespørgsler og lader ONLY_FULL_GROUP_BY som aktiveret.



  1. Repræsenterer IPv4/IPv6-adresser i Oracle

  2. Softwaregennemgang – Stellar Repair til MS SQL

  3. Sådan opretter du en ikke-nul kolonne i en visning

  4. Forskellig repræsentation af UUID i Java Hibernate og SQL Server