回答編集履歴

3

EXPLAINは誤解を避けるため、変更、追記

2020/09/19 22:14

投稿

xebme
xebme

スコア1081

test CHANGED
@@ -112,7 +112,7 @@
112
112
 
113
113
 
114
114
 
115
- 以下の2つのSQLはおなじです。
115
+ 以下の2つのSQLはじです。
116
116
 
117
117
 
118
118
 
@@ -126,4 +126,36 @@
126
126
 
127
127
 
128
128
 
129
+ **補足**
130
+
131
+
132
+
129
- 補足:EXPLAINを使ってSQLを確認しました。最初に提示したSQLは`SUBQUERY`でなく`UNCACHEABLE SUBQUERY`が表示されました。しかし対象が導出表だったので同じ結果が得られると判断しました。
133
+ EXPLAINを使ってSQLを確認しました。以下のSQLは`SUBQUERY`でなく`UNCACHEABLE SUBQUERY`が表示されました。しかし対象が導出表だったので同じ結果が得られると判断しました。
134
+
135
+
136
+
137
+ ```SQL
138
+
139
+ MariaDB [...]> explain SELECT * From data where id = (SELECT R FROM (SELECT CEIL(RAND() * (select count(*) from data)) AS R) RND);
140
+
141
+ +------+----------------------+------------+--------+---------------+---------+---------+-------+--------+----------------+
142
+
143
+ | id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
144
+
145
+ +------+----------------------+------------+--------+---------------+---------+---------+-------+--------+----------------+
146
+
147
+ | 1 | PRIMARY | data | const | PRIMARY | PRIMARY | 8 | const | 1 | Using where |
148
+
149
+ | 2 | UNCACHEABLE SUBQUERY | <derived3> | system | NULL | NULL | NULL | NULL | 1 | |
150
+
151
+ | 3 | DERIVED | NULL | NULL | NULL | NULL | NULL | NULL | NULL | No tables used |
152
+
153
+ | 4 | SUBQUERY | data | index | NULL | PRIMARY | 8 | NULL | 100239 | Using index |
154
+
155
+ +------+----------------------+------------+--------+---------------+---------+---------+-------+--------+----------------+
156
+
157
+ 4 rows in set (0.043 sec)
158
+
159
+ ```
160
+
161
+ これ以外のSQLのEXPLAINの結果は想定どおりでした。

2

結論

2020/09/19 22:13

投稿

xebme
xebme

スコア1081

test CHANGED
@@ -105,3 +105,25 @@
105
105
 
106
106
 
107
107
  最後に、質問の現象はどのテーブルでも再現できます。where条件に ceil(rand() * (select count(*) from <table>))と書けばよい。
108
+
109
+
110
+
111
+ **結論**
112
+
113
+
114
+
115
+ 以下の2つのSQLはおなじです。
116
+
117
+
118
+
119
+ ```SQL
120
+
121
+ SELECT * From data where id = CEIL(RAND() * (select count(*) from data));
122
+
123
+ SELECT id,datum,created_at,updated_at From (select *, CEIL(RAND() * (select count(*) from data)) from data) rnd where id=`CEIL(RAND() * (select count(*) from data))`;
124
+
125
+ ```
126
+
127
+
128
+
129
+ 補足:EXPLAINを使ってSQLを確認しました。最初に提示したSQLは`SUBQUERY`でなく`UNCACHEABLE SUBQUERY`が表示されました。しかし対象が導出表だったので同じ結果が得られると判断しました。

1

式の評価はレコードごとに行われる

2020/09/19 10:12

投稿

xebme
xebme

スコア1081

test CHANGED
@@ -83,3 +83,25 @@
83
83
  SELECT * From data where id = (SELECT RID FROM CIL);
84
84
 
85
85
  ```
86
+
87
+
88
+
89
+ **CEIL(RAND() * (select count(*) from data))はレコードごとに実行される**
90
+
91
+
92
+
93
+ 理由は、idと上の式の値が等しいかを判定するために、式を評価するからです。次のSQLを考えてください。これらの条件式はレコードごとに評価しています。
94
+
95
+
96
+
97
+ ```SQL
98
+
99
+ select * from data where id % 2 = 0 limit 5;
100
+
101
+ select * from data where id = power(ceil(rand()*10000),0);
102
+
103
+ ```
104
+
105
+
106
+
107
+ 最後に、質問の現象はどのテーブルでも再現できます。where条件に ceil(rand() * (select count(*) from <table>))と書けばよい。