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

黄舟
リリース: 2018-05-15 14:14:58
オリジナル
3265 人が閲覧しました

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';
ログイン後にコピー
<br/> ユーザーの最終ログイン時刻を調べるだけの場合は、次のように書くだけです:

+----+------+---------------+---------------------+
| 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;
ログイン後にコピー
<br/> ユーザーの最終ログインに関する他の情報もクエリする必要がある場合、この 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 |
+------+---------------------+
ログイン後にコピー
<br/>このようなステートメントは SQL 標準ではありませんが、MySQL データベースでは正常に実行できますが、返される結果は不明です

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

-- 错误写法
SELECT uid, ip, max(login_time)
FROM tb
GROUP BY uid;
-- 错误写法
ログイン後にコピー
<br/>おそらく ip フィールドは uid グループ化の前に最初の行の値を取得することは明らかに必須の情報ではありません

書き方 1

サブクエリを書く:<br/><br/>

<br/>
ログイン後にコピー
<br/>書き方 2

または別の方法writing:

<br/>

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);
ログイン後にコピー
<br/> ちなみに、5.6でテストしてみました。 以前のバージョンでは、このSQL文②の実行計画は、データ量が多い場合には理想的ではなく、見た目のパフォーマンスも悪かったです。

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

5.5.50: <br/><br/>

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);
ログイン後にコピー
<br/>5.6.30: <br/>

+----+--------------------+-------+------+---------------+------+---------+------+------+-------------+
| 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を直接書くと改善されます<br/>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           |
+----+--------------------+-------+------+---------------+------+---------+------------+------+-------------+
ログイン後にコピー
<br/> もちろん、結果は同じです: <br/>

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 サイトの他の関連記事を参照してください。

ソース:php.cn
このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。
最新の問題
人気のチュートリアル
詳細>
最新のダウンロード
詳細>
ウェブエフェクト
公式サイト
サイト素材
フロントエンドテンプレート
私たちについて 免責事項 Sitemap
PHP中国語ウェブサイト:福祉オンライン PHP トレーニング,PHP 学習者の迅速な成長を支援します!