|
大家好,我有一个需要优化的查询。它的工作原理,但它的狗,表现明智。: ^' l& l R, a. G2 g
内容如下:; G) q1 c+ H' D2 Q8 w" |: S6 X
SELECT *
" h4 i, ]! o$ K' ^) \' _FROM (
( D5 @$ I" n& D" t* r SELECT *0 t. a) A( U; I8 r& `3 c
FROM views# H7 ^& b3 g% L- d% \" {
WHERE user_id = '1'8 R2 O! u G# M+ Y8 [! H/ T
ORDER BY
/ s) B6 O6 A9 C: v* ` page DESC- k [4 u3 \$ y% L' \) x
) v
& D" V; @4 U4 ^ ?" X) h( oGROUP BY
) u8 Z$ ~ ~# p) i1 ? v.session3 Y& Y2 `3 E- D; X
我正在跟踪查看不同页面的视图,并且我想知道每个会话的最高页面,以便了解在任何给定条件下他们的点击量(从头到尾查看所有页面)会议。8 q- b! o( ^# ?0 ?
基本上,我想做的是在GROUP之前对结果进行排序。以上是实现的,成本很高。
5 U. [2 _) D% n谁能用这个方法拍我的脑袋?谢谢你们!
. T1 q e3 ?+ x; I6 f: G* Z. \( r更新:
+ n- @+ I4 b# h说明:
2 C# t4 Y: y Z% V G. M1 o"1" "RIMARY" "" "ALL" \N \N \N \N "3545" "Using temporary; Using filesort"
5 v7 p3 O1 W+ r"2" "DERIVED" "views" "index" \N "page" "5" \N "196168" "Using where"0 ]6 N4 {/ S7 y6 h% z- x7 O8 M
模式:
* ]& t6 I, q6 l) IID int(8) unsigned (NULL) NO PRI (NULL) auto_increment select,insert,update,references
! Q; \' U# p1 C0 M( t. a% `page int(8) (NULL) YES MUL (NULL) select,insert,update,references , [( q2 L7 y* J3 n$ F+ h- } ~( f
user_id int(8) (NULL) YES (NULL) select,insert,update,references
" e# S3 ~# @. bsession int(8) (NULL) YES (NULL) select,insert,update,references
3 G, |+ u0 ^- W, T: N: E+ icreated datetime (NULL) NO select,insert,update,references! s3 A9 i4 f- \& l; a
索引信息:
0 J. D1 [% i1 h2 z; `% tviews 0 PRIMARY 1 ID A 196008 (NULL) (NULL) BTREE
9 @' o7 H! ?3 hviews 1 page 1 page A 259 (NULL) (NULL) YES BTREE! C3 y. Q: ]8 z4 p) t8 g* A
3 L, m8 }- g3 |! `5 O) T解决方案:8 l# P. ]" s' ~0 d( y; f" _
2 h* {/ ^, N' s$ ^1 G, d% F9 ^# n9 X- x+ w
4 n5 [ i. f+ X9 L% _' `- g
0 v! q W! R" v3 X* a. u我正在跟踪查看不同页面的视图,并且我想知道每个会话的最高页面,以便了解在任何给定条件下他们的点击量(从头到尾查看所有页面)会议。8 X% T6 j8 H! J, s+ t
* H% w9 x9 D8 h, j9 V. c* Q
分组之前先订购是一种非常不可靠的方法。
5 u. Z2 j+ x: ?0 [! d0 C( E$ y7 cMySQL扩展GROUP BY语法:您可以在SELECTandORDER BY子句中使用未分组和未聚合的字段。
: z- ?1 R" @" f' Y在这种情况下,page每个输出一个随机值session。
& J+ j* `% M& R文档
) h* s9 f, a8 I3 T5 o明确指出,您永远不应对将确切确定为哪个值做任何假设:
# ~: G" ?" h) P3 h/ b
% r6 m' U6 [* m; W" i7 J" n- U( ]如果您从GROUP
6 M. j0 g7 e/ a: _. f, ^BY零件中省略的列在组中不是恒定的,请不要使用此功能。服务器可以自由地从组中返回任何值,因此除非所有值都相同,否则结果是不确定的。
1 Z2 S' G4 L2 D$ i' \
1 z, h; r% i: t5 F但是,实际上,将返回扫描的第一行中的值。9 g y* T T* l
由于您ORDER BY page DESC在子查询中使用,因此该行恰好是page每个会话最多的行。) G6 m4 ]2 D, I8 I+ m0 l( Q
您不应该依赖它,因为此行为没有记录,并且如果在下一版本中将返回其他行,则不会将其视为错误。0 S. x, \9 N; ^0 R2 ^
但是,您甚至不必做这些令人讨厌的把戏。
( z, V2 L4 v5 Y5 ?, o; ^$ l% }只需使用聚合函数:) x6 S- p+ Q/ j& q/ x
SELECT MAX(page)0 q4 I0 V4 f( \7 {$ P& q! p N1 |8 v
FROM views
6 F4 h& E4 B2 a0 X% Q/ XWHERE user_id = '1'7 m f+ X# l+ D& q$ `/ I$ L
GROUP BY6 J7 F1 |! \2 @
session- e1 t6 ^9 }. V
这是记录在案的,干净的方法来做您想要的。$ ]! x6 J# w3 j- o w7 H
创建一个复合索引(user_id, session, page)以使查询运行更快。/ u& W- B8 R$ F- \8 F
如果您需要表中的所有列,而不仅是聚合的列,请使用以下语法:; `% X0 K# E2 W4 v
SELECT v.*5 e/ Y, m! d3 P( S1 g6 o2 p
FROM (
7 ~2 j" R$ i) J9 A& Q9 z5 V SELECT DISTINCT user_id, session
5 J6 k: C7 h- Y2 [+ t& b FROM views. Z9 d! r- g, i: H4 c9 G) H4 ]
) vo
+ Z1 M7 U' ]& D5 U$ h, ] BJOIN views v2 y# b5 [# a4 R3 ]$ t4 C$ J
ON v.id =
* u4 [) N0 X3 h6 a# z/ U P (* y/ m3 ?+ j7 U6 [
SELECT id- s6 F6 t* |7 u: |
FROM views vi" A8 G5 F6 c3 }4 l$ m# v. @
WHERE vi.user_id = vo.user_id& e- \; ? |+ z" h$ H
AND vi.session = vo.session
, r: u* i$ {# t& n S4 H5 _6 z2 p( @ ORDER BY
7 L+ a4 Z# k/ ^: ]5 M, d page DESC& n5 V8 L1 D* N# X
LIMIT 1% P0 p( J1 V2 n
)) v. x% p' |9 _# Z' h
这假设id是PRIMARY KEYon views。 |
|