|
大家好,我有一个需要优化的查询。它的工作原理,但它的狗,表现明智。4 ?+ j2 j2 ]5 p: I8 w8 f0 C. L
内容如下:, F0 ]7 @8 k/ \7 q1 \. \ q6 [
SELECT *
* j! L& \ |) @2 MFROM (
1 G9 Y$ a% j) U SELECT *
2 D: \& u8 t0 l5 n \ FROM views% l' I& a" Y! l3 M" E
WHERE user_id = '1': J! ] p4 W" f% t
ORDER BY J; V3 l0 w$ |+ G& D
page DESC& R4 t! B/ L8 n2 C8 I+ X$ C
) v2 ]# E$ \! C* E7 n5 E/ w! U% Q4 D8 @
GROUP BY
! c' T9 d, [! V. }5 E4 J" W v.session
7 ^2 U2 @' M* E+ i+ q! H我正在跟踪查看不同页面的视图,并且我想知道每个会话的最高页面,以便了解在任何给定条件下他们的点击量(从头到尾查看所有页面)会议。
. w. k* @& F o7 N3 ~$ d基本上,我想做的是在GROUP之前对结果进行排序。以上是实现的,成本很高。
9 v H5 p; i { I3 S7 y* G; T谁能用这个方法拍我的脑袋?谢谢你们!
3 r" {3 ^! D& |! L0 u& V) X更新:5 p$ J1 |( u$ h! `! v5 Y
说明:
* I3 ~# n6 X$ M4 k/ v"1" "RIMARY" "" "ALL" \N \N \N \N "3545" "Using temporary; Using filesort"
& k: j9 k+ R9 w"2" "DERIVED" "views" "index" \N "page" "5" \N "196168" "Using where"
2 G _: v6 H7 A2 |模式:7 a& b* r, ^, h
ID int(8) unsigned (NULL) NO PRI (NULL) auto_increment select,insert,update,references - v* D- ]0 C2 t. Q6 U; z9 Q# d
page int(8) (NULL) YES MUL (NULL) select,insert,update,references - I2 | e% h( Q; F, c5 Z0 x9 B2 t' s
user_id int(8) (NULL) YES (NULL) select,insert,update,references
9 u2 h# j- l% h6 e( ] w" R1 Y$ \' d Esession int(8) (NULL) YES (NULL) select,insert,update,references ' |0 {0 Q! c$ d" \/ @4 X
created datetime (NULL) NO select,insert,update,references
& ^* e# @5 \) a/ G索引信息:' L% t; g4 ?; P" {
views 0 PRIMARY 1 ID A 196008 (NULL) (NULL) BTREE) {' P7 h% g7 Y) T/ M. Y
views 1 page 1 page A 259 (NULL) (NULL) YES BTREE
* _8 O8 I. ~( A; L1 H
. T3 \; s& R/ v: l7 H2 b解决方案:1 c6 [" U* M( R/ A2 D
4 F w+ K$ Z% V. y7 s8 y- z7 G$ S7 d5 ~1 n5 e/ m; [6 }* }
$ L6 W0 [; W" k, D7 w2 }
, n: o/ ^; G$ W我正在跟踪查看不同页面的视图,并且我想知道每个会话的最高页面,以便了解在任何给定条件下他们的点击量(从头到尾查看所有页面)会议。- a# a3 h8 W9 R3 {4 j+ h, m# z* t
4 \# } R k: x0 [* v1 t O
分组之前先订购是一种非常不可靠的方法。0 `4 @. k- f3 @, t& x
MySQL扩展GROUP BY语法:您可以在SELECTandORDER BY子句中使用未分组和未聚合的字段。5 H& m. k. A) l
在这种情况下,page每个输出一个随机值session。
6 Z- k% [: c5 ^% e& m' |2 b- y9 t文档
+ ~' e" N8 l) ~! V# c! d明确指出,您永远不应对将确切确定为哪个值做任何假设:0 S0 a4 M9 T% T4 Q7 k7 W. g
8 N7 i, y6 L! t1 o! Y. E3 E( V6 w/ n$ O
如果您从GROUP
2 t- y' L3 k2 N: EBY零件中省略的列在组中不是恒定的,请不要使用此功能。服务器可以自由地从组中返回任何值,因此除非所有值都相同,否则结果是不确定的。
; G* T5 E. I) I: _' _7 J9 {' Q% C. D, R, Y3 p0 o# h) }
但是,实际上,将返回扫描的第一行中的值。* u; D& x9 i( h0 ^6 S. @0 O% f
由于您ORDER BY page DESC在子查询中使用,因此该行恰好是page每个会话最多的行。
' V7 X* s# R$ j0 V/ S" p2 s您不应该依赖它,因为此行为没有记录,并且如果在下一版本中将返回其他行,则不会将其视为错误。
" X2 N+ a& P4 H+ b$ Q. i' T1 K但是,您甚至不必做这些令人讨厌的把戏。- F% p# i. p/ n
只需使用聚合函数:% R' f& [9 l" r. V1 Z& n' V
SELECT MAX(page)& w8 ^! ^' Y l4 l* k
FROM views/ f) l( q* j9 f. d: @
WHERE user_id = '1'
5 \% k; g6 \9 eGROUP BY/ a- _& ^$ w5 L
session
- g0 ~* D$ j0 ~' u V0 {, o2 {这是记录在案的,干净的方法来做您想要的。 j, o; G' J8 i8 A+ T* ?
创建一个复合索引(user_id, session, page)以使查询运行更快。% ]* B5 q9 \7 p" a% o+ F$ B
如果您需要表中的所有列,而不仅是聚合的列,请使用以下语法:- {& o! U. h5 c$ Z; j' K
SELECT v.*7 T$ c+ t2 |5 f! a
FROM (1 p$ l, w) c: u+ I* Y3 k ]
SELECT DISTINCT user_id, session
$ G# W' ?1 u, W F$ l6 E FROM views! f4 x% J8 t$ }- P6 b3 y- u
) vo
" E/ ?2 k6 ]2 D/ t, ~2 WJOIN views v) G& ? T" L1 A' c- B
ON v.id =
& C; i2 `8 M* q" K& m/ { (7 w* F6 f8 e- l r9 _; G: A; Y1 `
SELECT id, k: j, q, P$ E- W/ J3 \
FROM views vi& c c* _' f; j, c2 G- @
WHERE vi.user_id = vo.user_id/ h9 _$ T5 ?2 ?! }/ n5 q& s4 a2 H) g
AND vi.session = vo.session9 x8 X d8 Q6 k" y+ c' A6 V1 u
ORDER BY* U2 n: }4 O ?8 b7 p
page DESC
% ?1 y/ M: L8 a X0 @. E# ]/ v. y LIMIT 1
' T) J2 N1 |1 S ), `6 u5 B% Z0 v1 W
这假设id是PRIMARY KEYon views。 |
|