回答編集履歴

1

コメントに対して追記

2017/01/20 12:13

投稿

KiyoshiMotoki
KiyoshiMotoki

スコア4791

test CHANGED
@@ -81,3 +81,157 @@
81
81
  2 rows in set (0.00 sec)
82
82
 
83
83
  ```
84
+
85
+
86
+
87
+ # 追記
88
+
89
+ > 一つずつ実行してようやく理解できました。
90
+
91
+ > 自分より大きいversionがないデータがNULLになって最大を求めているんですね。
92
+
93
+ > そしてもうひとつs3テーブルも同じようにjoinしてNULLが最大になる。
94
+
95
+
96
+
97
+ Good Job!
98
+
99
+ まさに、仰る通りです。
100
+
101
+
102
+
103
+ 以下のように SELECTリストを`*`に変更し、さらに WHERE句を削除したクエリを実行してみると、
104
+
105
+ よりイメージが掴みやすくなるかと思います。
106
+
107
+
108
+
109
+ ```sql
110
+
111
+ mysql> SELECT *
112
+
113
+ -> FROM test AS t1
114
+
115
+ -> LEFT OUTER JOIN test AS t2 ON t1.code = t2.code AND t1.version < t2.version
116
+
117
+ -> LEFT OUTER JOIN test AS t3 ON t1.code = t3.code AND t1.version = t3.version AND t1.variation < t3.variation;
118
+
119
+ +------+---------+-----------+------+---------+-----------+------+---------+-----------+
120
+
121
+ | code | version | variation | code | version | variation | code | version | variation |
122
+
123
+ +------+---------+-----------+------+---------+-----------+------+---------+-----------+
124
+
125
+ | BBB | 1 | 1 | BBB | 2 | 1 | BBB | 1 | 2 |
126
+
127
+ | AAA | 1 | 1 | AAA | 2 | 1 | NULL | NULL | NULL |
128
+
129
+ | AAA | 1 | 1 | AAA | 2 | 2 | NULL | NULL | NULL |
130
+
131
+ | AAA | 1 | 1 | AAA | 2 | 3 | NULL | NULL | NULL |
132
+
133
+ | BBB | 1 | 2 | BBB | 2 | 1 | NULL | NULL | NULL |
134
+
135
+ | AAA | 2 | 1 | NULL | NULL | NULL | AAA | 2 | 2 |
136
+
137
+ | AAA | 2 | 1 | NULL | NULL | NULL | AAA | 2 | 3 |
138
+
139
+ | AAA | 2 | 2 | NULL | NULL | NULL | AAA | 2 | 3 |
140
+
141
+ | AAA | 2 | 3 | NULL | NULL | NULL | NULL | NULL | NULL |
142
+
143
+ | BBB | 2 | 1 | NULL | NULL | NULL | NULL | NULL | NULL |
144
+
145
+ +------+---------+-----------+------+---------+-----------+------+---------+-----------+
146
+
147
+ 10 rows in set (0.02 sec)
148
+
149
+ ```
150
+
151
+
152
+
153
+ ---
154
+
155
+ > ちなみにこれはgroup byでも同じようなことができるのでしょうか?
156
+
157
+
158
+
159
+ 実は、本回答は以下のページの"LEFT JOIN"バージョンの応用です。
160
+
161
+ [https://dev.mysql.com/doc/refman/5.6/ja/example-maximum-column-group-row.html](https://dev.mysql.com/doc/refman/5.6/ja/example-maximum-column-group-row.html)
162
+
163
+
164
+
165
+ もし、ご興味があれば、上のページの"相関サブクエリー"バージョンと"非相関サブクエリー"バージョンで同様の結果を得られないか、チャレンジしてみてください。
166
+
167
+ (私は力尽きたので、これ以上は深追いしません(^^; )
168
+
169
+
170
+
171
+ ---
172
+
173
+ > パフォーマンス的にはgroup byを使うよりこちらの方がよかったりしますか?
174
+
175
+
176
+
177
+ インデックスの有無やレコード数、値の分布具合にもよるので、何とも言えません。
178
+
179
+ ご自身の環境でそれぞれのバージョンのクエリを実行し、比較してみてください。
180
+
181
+
182
+
183
+ もっとも、手元の環境で確認した限りでは、
184
+
185
+ 私の回答のクエリで`(code, version, variation)`という複合インデックスが効きました。
186
+
187
+
188
+
189
+ そのため、上記複合インデックスを作成すれば、
190
+
191
+ "相関サブクエリー"バージョン・"非相関サブクエリー"バージョンのクエリと比べて
192
+
193
+ 「明らかに分が悪い」
194
+
195
+ ということにはならないかと、予想します。
196
+
197
+
198
+
199
+ ```sql
200
+
201
+ mysql> ALTER TABLE test ADD INDEX (code, version, variation);
202
+
203
+ Query OK, 0 rows affected (0.04 sec)
204
+
205
+ Records: 0 Duplicates: 0 Warnings: 0
206
+
207
+
208
+
209
+ mysql> EXPLAIN SELECT t1.*
210
+
211
+ -> FROM test AS t1
212
+
213
+ -> LEFT OUTER JOIN test AS t2 ON t1.code = t2.code AND t1.version < t2.version
214
+
215
+ -> LEFT OUTER JOIN test AS t3 ON t1.code = t3.code AND t1.version = t3.version AND t1.variation < t3.variation
216
+
217
+ -> WHERE t2.code IS NULL
218
+
219
+ -> AND t3.code IS NULL;
220
+
221
+ +----+-------------+-------+------------+-------+---------------+------+---------+------------------------------+------+----------+--------------------------+
222
+
223
+ | id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra |
224
+
225
+ +----+-------------+-------+------------+-------+---------------+------+---------+------------------------------+------+----------+--------------------------+
226
+
227
+ | 1 | SIMPLE | t1 | NULL | index | NULL | code | 21 | NULL | 7 | 100.00 | Using index |
228
+
229
+ | 1 | SIMPLE | t2 | NULL | ref | code | code | 11 | test.t1.code | 3 | 100.00 | Using where; Using index |
230
+
231
+ | 1 | SIMPLE | t3 | NULL | ref | code | code | 16 | test.t1.code,test.t1.version | 1 | 100.00 | Using where; Using index |
232
+
233
+ +----+-------------+-------+------------+-------+---------------+------+---------+------------------------------+------+----------+--------------------------+
234
+
235
+ 3 rows in set, 1 warning (0.05 sec)
236
+
237
+ ```