问题描述
我正在跟踪查看不同页面的视图,并且我想知道每个会话的最高页面,以便了解在任何给定条件下他们的点击量(从头到尾查看所有页面)会议。
分组之前先订购是一种非常不可靠的方法。
MysqL
扩展GROUP BY
语法:您可以在SELECT
andORDER BY
子句中使用未分组和未聚合的字段。
如果您从
GROUP BY
零件中省略的列在组中不是恒定的,请不要使用此功能。服务器可以自由地从组中返回任何值,因此除非所有值都相同,否则结果是不确定的。
但是,实际上,将返回扫描的第一行中的值。
由于您ORDER BY page DESC
在子查询中使用,因此该行恰好是page
每个会话最多的行。
您不应该依赖它,因为此行为没有记录,并且如果在下一版本中将返回其他行,则不会将其视为错误。
但是,您甚至不必做这些令人讨厌的把戏。
只需使用聚合函数:
SELECT MAX(page)
FROM views
WHERE user_id = '1'
GROUP BY
session
这是记录在案的,干净的方法来做您想要的。
创建一个复合索引(user_id, session, page)
以使查询运行更快。
如果您需要表中的所有列,而不仅是聚合的列,请使用以下语法:
SELECT v.*
FROM (
SELECT disTINCT user_id, session
FROM views
) vo
JOIN views v
ON v.id =
(
SELECT id
FROM views vi
WHERE vi.user_id = vo.user_id
AND vi.session = vo.session
ORDER BY
page DESC
LIMIT 1
)
这假设id
是PRIMARY KEY
on views
。
解决方法
大家好,我有一个需要优化的查询。它的工作原理,但它的狗,表现明智。
内容如下:
SELECT *
FROM (
SELECT *
FROM views
WHERE user_id = '1'
ORDER BY
page DESC
) v
GROUP BY
v.session
我正在跟踪查看不同页面的视图,并且我想知道每个会话的最高页面,以便了解在任何给定条件下他们的点击量(从头到尾查看所有页面)会议。
基本上,我想做的是在GROUP之前对结果进行排序。以上是实现的,成本很高。
谁能用这个方法拍我的脑袋?谢谢你们!
更新:
说明:
"1" "PRIMARY" "<derived2>" "ALL" \N \N \N \N "3545" "Using temporary; Using filesort"
"2" "DERIVED" "views" "index" \N "page" "5" \N "196168" "Using where"
模式:
ID int(8) unsigned (NULL) NO PRI (NULL) auto_increment select,insert,update,references
page int(8) (NULL) YES MUL (NULL) select,references
user_id int(8) (NULL) YES (NULL) select,references
session int(8) (NULL) YES (NULL) select,references
created datetime (NULL) NO select,references
索引信息:
views 0 PRIMARY 1 ID A 196008 (NULL) (NULL) BTREE
views 1 page 1 page A 259 (NULL) (NULL) YES BTREE