用于从数据库返回新访问者的MySQL查询
假设我有一个记录传入用户的表,其中每个用户都有一个IP地址(ipaddr) 选择以前从未访问过该网站的所有用户的最佳方式是什么?(因此特定的IPADDR值只在表中存在一次),但是我只想知道过去6小时内新来的访客的情况 我基本上希望在SQL中执行类似的操作:用于从数据库返回新访问者的MySQL查询,mysql,optimization,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' 但是,日期条件应仅适用于结果,而不适用于检
SELECT * from visitors GROUP BY ipaddr WHERE COUNT(ipaddr) = 1 and date > '2011-03-31 00:59:11'
但是,日期条件应仅适用于结果,而不适用于检查访客是否为新访客
更新:
有一个SID字段用于说明用户浏览会话
以下是相关的表架构:
CREATE TABLE `visitors` (
`date` timestamp NOT NULL default CURRENT_TIMESTAMP,
`sid` bigint(12) unsigned NOT NULL,
`ipaddr` int(8) NOT NULL,
)
一些示例数据:
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);
此访问者有两行用于实时执行当前会话,每行用于他访问过的每个页面(仅显示相关架构)。显示的最后一个示例行是2010年的访问,这意味着该ip地址有两个不同的SID属于它,因此不是新的访问者
查询的结果不应该包含上面列出的任何一行,因为这个访问者在数据库中有两个会话。如果删除了最后一行(sid为694387538590),则访问者应成为新访问者并出现在查询中。其中分组依据的是具有:
SELECT ipaddr from visitors
GROUP BY ipaddr
HAVING COUNT(ipaddr) = 1 AND MIN(date) > '2011-03-31 00:59:11'
更新
说明:
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
SELECT
中的授权列包括:
分组依据
子句中使用的列
- 其他柱子的一个门
ipaddr
在组中使用,而不是sid
。为了也有sid
,我使用了MAX,但请记住,它将仅应用于当前ipaddr
的行组,并且由于查询中的条件,有1个唯一的sid
,但会重复,因此结果将是sid
Hmm这似乎与我描述的一样。你能解释一下这个查询是如何工作的吗?我认为GROUP BY是在拥有之前应用的,因此GROUP BY将为每个IPADR留下1行。那么,对于GROUP BY之后剩下的所有行,count(ipaddr)不是等于1吗?HAVING子句用于过滤聚合(SUM、count、AVG),WHERE子句根据条件过滤。因此它首先按分组,然后消除所有不符合HAVING条件的记录。HAVING
子句与聚合函数一起使用,以筛选由GROUP BY
生成的组,即:在返回IPADR
之前,计数(IPADR)=1
是根据具有ipaddr
的行组进行评估的。谢谢大家,这非常有用!在IPADDR上有一个索引有意义吗,或者不使用该索引有意义吗?
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