ホームページ  >  記事  >  データベース  >  MySQL - GROUP BY グループ化してフィールドの最大値を取得するサンプルコードの詳細

MySQL - GROUP BY グループ化してフィールドの最大値を取得するサンプルコードの詳細

黄舟
黄舟オリジナル
2018-05-15 14:14:583356ブラウズ

MySQL - サンプル コードの詳細を GROUP BY グループ化して最大フィールド値を取得します:

ユーザーのログイン レコード情報をクエリする必要があるビジネス シナリオがあるとします。テーブル構造は次のとおりです。データ:

CREATE TABLE `tb` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `uid` int(11) NOT NULL,
  `ip` varchar(16) NOT NULL,
  `login_time` datetime,
  PRIMARY KEY (`id`),
  KEY (`uid`)
);

table データ状況:

INSERT INTO tb SELECT null, 1001, '192.168.1.1', '2017-01-21 16:30:47';
INSERT INTO tb SELECT null, 1003, '192.168.1.153', '2017-01-21 19:30:51';
INSERT INTO tb SELECT null, 1001, '192.168.1.61', '2017-01-21 16:50:41';
INSERT INTO tb SELECT null, 1002, '192.168.1.31', '2017-01-21 18:30:21';
INSERT INTO tb SELECT null, 1002, '192.168.1.66', '2017-01-21 19:12:32';
INSERT INTO tb SELECT null, 1001, '192.168.1.81', '2017-01-21 19:53:09';
INSERT INTO tb SELECT null, 1001, '192.168.1.231', '2017-01-21 19:55:34';

ユーザーの最終ログイン時刻を調べるだけの場合は、次のように書くだけです:

+----+------+---------------+---------------------+
| id | uid  | ip            | login_time          |
+----+------+---------------+---------------------+
| 1  | 1001 | 192.168.1.1   | 2017-01-21 16:30:47 |
| 2  | 1003 | 192.168.1.153 | 2017-01-21 19:30:51 |
| 3  | 1001 | 192.168.1.61  | 2017-01-21 16:50:41 |
| 4  | 1002 | 192.168.1.31  | 2017-01-21 18:30:21 |
| 5  | 1002 | 192.168.1.66  | 2017-01-21 19:12:32 |
| 6  | 1001 | 192.168.1.81  | 2017-01-21 19:53:09 |
| 7  | 1001 | 192.168.1.231 | 2017-01-21 19:55:34 |
+----+------+---------------+---------------------+
SELECT uid, max(login_time)
FROM tb
GROUP BY uid;

ユーザーの最終ログインに関する他の情報もクエリする必要がある場合、この SQL を使用して次のように書くことはできません:

+------+---------------------+
| uid  | max(login_time)       |
+------+---------------------+
| 1001 | 2017-01-21 19:55:34 |
| 1002 | 2017-01-21 19:12:32 |
| 1003 | 2017-01-21 19:30:51 |
+------+---------------------+

このようなステートメントは SQL 標準ではありませんが、MySQL データベースでは正常に実行できますが、返される結果は不明です

(sql_mode がonly_full_group_by に設定されている場合は、実行されません)。 )

-- 错误写法
SELECT uid, ip, max(login_time)
FROM tb
GROUP BY uid;
-- 错误写法

おそらく ip フィールドは uid グループ化の前に最初の行の値を取得することは明らかに必須の情報ではありません

書き方 1

サブクエリを書く:

<br/>

書き方 2

または別の方法writing:


SELECT a.uid, a.ip, a.login_time
FROM tb a
WHERE a.login_time in (
SELECT max(login_time)
FROM tb
GROUP BY uid);

ちなみに、5.6でテストしてみました。 以前のバージョンでは、このSQL文②の実行計画は、データ量が多い場合には理想的ではなく、見た目のパフォーマンスも悪かったです。

5.6以降のバージョンでは、②のこのSQLの書き方がかなり速くなり、実行計画も変わりました

5.5.50:

SELECT a.uid, a.ip, a.login_time
FROM tb a
WHERE a.login_time = (
SELECT max(login_time)
FROM tb
WHERE a.uid = uid);

5.6.30:

+----+--------------------+-------+------+---------------+------+---------+------+------+-------------+
| id | select_type        | table | type | possible_keys | key  | key_len | ref  | rows | Extra       |
+----+--------------------+-------+------+---------------+------+---------+------+------+-------------+
| 1  | PRIMARY            | a     | ALL  | NULL             | NULL  | NULL      | NULL | 7    | Using where |
| 2  | DEPENDENT SUBQUERY | tb    | ALL  | uid           | NULL  | NULL      | NULL | 7    | Using where |
+----+--------------------+-------+------+---------------+------+---------+------+------+-------------+

3を直接書くと改善されます
joinに直接変更すると改善されますパフォーマンスが良い:

+----+--------------------+-------+------+---------------+------+---------+------------+------+-------------+
| id | select_type        | table  | type | possible_keys | key  | key_len | ref       | rows  | Extra      |
+----+--------------------+-------+------+---------------+------+---------+------------+------+-------------+
| 1  | PRIMARY            | a     | ALL  | NULL              | NULL | NULL      | NULL        | 7    | Using where |
| 2  | DEPENDENT SUBQUERY | tb    | ref  | uid           | uid  | 4       | test.a.uid | 1    | NULL           |
+----+--------------------+-------+------+---------------+------+---------+------------+------+-------------+

もちろん、結果は同じです:

SELECT a.uid, a.ip, a.login_time
FROM (SELECT uid, max(login_time) login_time
FROM tb
GROUP BY uid
) b JOIN tb a ON a.uid = b.uid AND a.login_time = b.login_time;


注: 最小値をグループ化したい場合は、対応する関数とシンボルを変更するだけです。

以上がMySQL - GROUP BY グループ化してフィールドの最大値を取得するサンプルコードの詳細の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。