用于从数据库返回新访问者的MySQL查询

时间:2011-03-30 21:31:06

标签: 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'

但是,DATE条件应该仅适用于结果,而不是用于检查访问者是否是新的。

更新:

有一个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地址有2个不同的SID属于它,因此不是新访问者。

查询的结果应该没有上面列出的任何行,看看此访问者在数据库中有两个会话。如果删除了最后一行(使用sid 694387538590),则访问者应成为新访问者并显示在查询中。

1 个答案:

答案 0 :(得分:5)

"WHERE"的{​​{1}}为GROUP BY

HAVING

更新

SELECT ipaddr from visitors
GROUP BY ipaddr
HAVING COUNT(ipaddr) = 1 AND MIN(date) > '2011-03-31 00:59:11'

<强>解释

SELECT ipaddr, max(sid) sid
  FROM visitors
 GROUP BY ipaddr
HAVING     COUNT(DISTINCT sid) = 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子句
  • 中使用的列
  • 聚集其他列

GROUP BY在GROUP BY中使用,但未在ipaddr中使用。还要sid我使用了MAX,但请记住它只会应用于当前sid的行组,并且由于查询中的条件有1个唯一ipaddr但重复结果将是sid