use*_*146 1 mysql optimization
假设我有一个表记录每个用户拥有IP地址(ipaddr)的传入用户.
选择之前从未访问过网站的所有用户的最佳方法是什么?(这样特定的IPADDR值只存在于表中一次),但我只想知道过去6小时内出现的新访问者.
我基本上想在SQL中做这样的事情:
SELECT * from visitors GROUP BY ipaddr WHERE COUNT(ipaddr) = 1 and date > '2011-03-31 00:59:11'
Run Code Online (Sandbox Code Playgroud)
但是,DATE条件应仅适用于结果,而不适用于检查访问者是否是新的.
更新:
有一个SID字段可以解释用户浏览会话.
这是相关的表模式:
CREATE TABLE `visitors` (
`date` timestamp NOT NULL default CURRENT_TIMESTAMP,
`sid` bigint(12) unsigned NOT NULL,
`ipaddr` int(8) NOT NULL,
)
Run Code Online (Sandbox Code Playgroud)
一些示例数据:
INSERT INTO `visitors` (`date`,`sid`, `ipaddr`)
VALUES
('2011-03-31 06:25:48', 299521885457, -1454342140);
INSERT INTO `visitors` (`date`,`sid`, `ipaddr`)
VALUES
('2011-03-31 06:26:37', 299521885457, -1454342140);
INSERT INTO `visitors` (`date`,`sid`, `ipaddr`)
VALUES
('2010-01-01 15:23:44', 694387538590, -1454342140);
Run Code Online (Sandbox Code Playgroud)
该访问者有两行实时发生当前会话,每行都是他访问过的每一页(仅显示相关的模式).显示的最后一个示例行是2010年的访问,这意味着此IP地址有2个不同的SID属于它,因此不是新访问者.
查询的结果应该没有上面列出的任何行,看看此访问者在数据库中有两个会话.如果删除了最后一行(使用sid 694387538590),则访问者应成为新访问者并显示在查询中.
在"WHERE"为GROUP BY是HAVING:
SELECT ipaddr from visitors
GROUP BY ipaddr
HAVING COUNT(ipaddr) = 1 AND MIN(date) > '2011-03-31 00:59:11'
Run Code Online (Sandbox Code Playgroud)
SELECT ipaddr, max(sid) sid
FROM visitors
GROUP BY ipaddr
HAVING COUNT(DISTINCT sid) = 1
AND MIN(date) > '2011-03-31 00:59:11'
Run Code Online (Sandbox Code Playgroud)
说明:
SELECT date, sid, ipaddr FROM visitors
date sid ipaddr
------------------------------------------
2011-03-31 06:25:48 299525457 -1454342140
2011-03-31 06:26:37 299525457 -1454342140
2010-01-01 15:23:44 694388590 -1454342140
2011-03-31 11:23:44 111111111 -1234444811
2011-03-31 12:23:44 111111111 -1234444811
SELECT ipaddr FROM visitors GROUP BY ipaddr
ipaddr
-----------
-1454342140
-1234444811
--- group for ip -1454342140 ---
2011-03-31 06:25:48 299525457 -1454342140
2011-03-31 06:26:37 299525457 -1454342140
2010-01-01 15:23:44 694388590 -1454342140
COUNT(DISTINCT sid) = COUNT(299525457, 694388590) = 2
--> there is more than 1 session for this ip: not good!!!
==> group discarded
--- group for ip -1234444811 ---
2011-03-31 11:23:44 111111111 -1234444811
2011-03-31 12:23:44 111111111 -1234444811
COUNT(DISTINCT sid) = COUNT(111111111) = 1 --> OK
(here COUNT(sid) = count(111111111, 111111111) = 2
--> despite it is the same sid, the count is 2, that is why using DISTINCT)
MIN(date) = '2011-03-31 11:23:44' > '2011-03-31 00:59:11' --> OK
==> group accepted
Run Code Online (Sandbox Code Playgroud)
授权栏中SELECT有:
GROUP BY子句中使用的列ipaddr在GROUP BY中使用但不是sid.sid我也使用了MAX,但请记住它只会应用于当前的行组,ipaddr因为查询中的条件有1个唯一sid但重复的,所以结果将是sid