MySQL 5.7より前のデフォルトでは、完全でないgroup by
を許可していました。 。つまり、group by(sum
などの集計関数を使用)を作成できます。 およびmax
およびcount
およびgroup_concat
)他の非集計列(NON AGGS
と呼びましょう) )最初の3つが表示されているようにすべてではありません group by
の一部 句。それはそれを可能にしましたが、結果は通常次のようになります:
-
あなたはあなたのデータをよく知っていて、明確なものを達成しようとしているので、それはうまくいきました
-
それはスナフだったのでひどい結果になりました
5.7より前のバージョンでは、ONLY_FULL_GROUP_BY
存在しましたが、デフォルトでオフになっています。
したがって、MySQL 5.7には、ONLY_FULL_GROUP_BY
が付属しています。 デフォルトはオンです。そのため、グループ化を試みる場合、ただしすべてではない NON AGGS
group by
句を指定すると、エラーが発生します。
以下の5.6の次の問題を検討してください。
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 |
+------+------+----------+
上記で発生するのは、すべてのNON AGGS
ではありません。 group by
に含まれています 。 max(age)をcol1で返します。しかし、col2
以降 group by
に含まれていませんでした 、クラスターインデックスまたは物理順序を使用して、誤って(snafu、間違い)col2の値を間違えました。あなたの意図に応じて、またはあなたのデータを知っているか、あるいは思いやりさえあります。エンジンは気にしませんでした。おそらくあなたはそうします。
これらの一般的な間違いや不注意によるデータの返送を回避するために、MySQL5.7はONLY_FULL_GROUP_BY
をオンにします。 デフォルトで。
あなたの場合、間違った行がおそらく列2と3の結果を構成しています。
MySQLによるGROUPBYの処理<というタイトルのマニュアルページを参照してください。 / a> 。
例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);
クエリ:
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 |
+-----------+----------+-------------+
上記は、ONLY_FULL_GROUP_BY
の設定に関係なく、MySQL5.6および5.7でうまく機能します。
今考えてください
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 |
+-----------+----------+-------------+
上記は、ONLY_FULL_GROUP_BY
がなくてもMySQL5.6で受け入れられることがよくあります。 5.7で有効になり、ONLY_FULL_GROUP_BY
で失敗します 有効(エラー1055)。上記の出力は基本的にぎこちないものです。しかし、以下でいくらか説明されています:
私たちは、Dirk、Dirk、たった1つのDirkが、内部結合を生き残る唯一のDirkであることを知っています。 2つのダークがあります。しかし、group by p.firstName
のため、 、Dirkが1つだけ残っています。 lastName
が必要です 。
SQL標準に準拠していないため、MySQLはONLY_FULL_GROUP_BY
でこれを許可できます。 オフになりました。したがって、古いlastNameを選択するだけです。さて、それが最初に見つけたもの、そしてそれはキャッシュまたは物理的な順序のいずれかにあります。
そしてそれはピーターズと一緒に行きました。フルーツカウントの合計は、すべてのダークに適用されます。
したがって、このようにコーディングすると、不適合の非ONLY_FULL_GROUP_BY
ぎこちないものになります。
そして述べたように、MySQL5.7の出荷はデフォルトでこれを許可していません。ただし、必要に応じて、古い方法に調整できます。
クエリを修正し、ONLY_FULL_GROUP_BY
のままにすることを強くお勧めします 有効になっています。