我跟踪网络访问者。我存储了IP地址以及访问的时间戳。
ip_address time_stamp
180.2.79.3 1301654105
180.2.79.3 1301654106
180.2.79.3 1301654354
180.2.79.3 1301654356
180.2.79.3 1301654358
180.2.79.3 1301654366
180.2.79.3 1301654368
180.2.79.3 1301654422
我有一个查询来获取总曲目:
SELECT COUNT(*) AS tracks FROM tracking
但是,我现在想要忽略每次访问后10秒内多次访问过的用户的访问。由于我不考虑这次访问,它仍然是第一次访问的一部分。
当ip_address相同时,请检查 时间戳,只计算那些行 距离每个都有10秒钟 其他
我很难将它放入SQL查询表单中,我将不胜感激任何帮助!
答案 0 :(得分:15)
让我先从这张桌子开始。我会使用普通的时间戳,这样我们就可以很容易地看到发生了什么。
180.2.79.3 2011-01-01 08:00:00
180.2.79.3 2011-01-01 08:00:09
180.2.79.3 2011-01-01 08:00:20
180.2.79.3 2011-01-01 08:00:23
180.2.79.3 2011-01-01 08:00:25
180.2.79.3 2011-01-01 08:00:40
180.2.79.4 2011-01-01 08:00:00
180.2.79.4 2011-01-01 08:00:13
180.2.79.4 2011-01-01 08:00:23
180.2.79.4 2011-01-01 08:00:25
180.2.79.4 2011-01-01 08:00:27
180.2.79.4 2011-01-01 08:00:29
180.2.79.4 2011-01-01 08:00:50
如果我理解正确,你想要这样计算。
180.2.79.3 3
180.2.79.4 3
您可以通过选择
的最大时间戳来为每个ip_address执行此操作将这两个标准放在一起会引入一些空值,结果证明它们非常有用。
select ip_address,
t_s.time_stamp,
(select max(t.time_stamp)
from t_s t
where t.ip_address = t_s.ip_address
and t.time_stamp > t_s.time_stamp
and t.time_stamp - t_s.time_stamp <= interval '10' second) next_page
from t_s
group by ip_address, t_s.time_stamp
order by ip_address, t_s.time_stamp;
ip_address time_stamp next_page
180.2.79.3 2011-01-01 08:00:00 2011-01-01 08:00:09
180.2.79.3 2011-01-01 08:00:09 <null>
180.2.79.3 2011-01-01 08:00:20 2011-01-01 08:00:25
180.2.79.3 2011-01-01 08:00:23 2011-01-01 08:00:25
180.2.79.3 2011-01-01 08:00:25 <null>
180.2.79.3 2011-01-01 08:00:40 <null>
180.2.79.4 2011-01-01 08:00:00 <null>
180.2.79.4 2011-01-01 08:00:13 2011-01-01 08:00:23
180.2.79.4 2011-01-01 08:00:23 2011-01-01 08:00:29
180.2.79.4 2011-01-01 08:00:25 2011-01-01 08:00:29
180.2.79.4 2011-01-01 08:00:27 2011-01-01 08:00:29
180.2.79.4 2011-01-01 08:00:29 <null>
180.2.79.4 2011-01-01 08:00:50 <null>
标记访问结束的时间戳对于其自己的next_page而言为null。那是因为没有时间戳小于或等于该行的time_stamp + 10秒。
为了得到一个计数,我可能会创建一个视图并计算空值。
select ip_address, count(*)
from t_s_visits
where next_page is null
group by ip_address
180.2.79.3 3
180.2.79.4 3
答案 1 :(得分:6)
您可以JOIN
自己跟踪表,并通过添加WHERE
子句过滤掉您不需要的记录。
SELECT t1.ip_address
, COUNT(*) AS tracks
FROM tracking t1
LEFT OUTER JOIN tracking t2 ON t2.ip_address = t1.ip_address
AND t2.time_stamp < t1.time_stamp + 10
WHERE t2.ip_adress IS NULL
GROUP BY
t1.ip_address
修改强>
以下脚本在SQL Server中工作,但我不能在单个SQL语句中表达它,更不用说将其转换为MySQL。它可能会给你一些关于所需内容的指示。
注意:我假设对于给定的输入,应该选择数字1和11。
;WITH q (number) AS (
SELECT 1
UNION ALL SELECT 2
UNION ALL SELECT 10
UNION ALL SELECT 11
UNION ALL SELECT 12
)
SELECT q1.Number as n1
, q2.Number as n2
, 0 as Done
INTO #Temp
FROM q q1
LEFT OUTER JOIN q q2 ON q2.number < q1.number + 10
AND q2.number > q1.number
DECLARE @n1 INTEGER
DECLARE @n2 INTEGER
WHILE EXISTS (SELECT * FROM #Temp WHERE Done = 0)
BEGIN
SELECT TOP 1 @n1 = n1
, @n2= n2
FROM #Temp
WHERE Done = 0
DELETE FROM #Temp
WHERE n1 = @n2
UPDATE #Temp
SET Done = 1
WHERE n1 = @n1
AND n2 = @n2
END
SELECT DISTINCT n1
FROM #Temp
DROP TABLE #Temp
答案 2 :(得分:2)
最简单的方法是将时间戳除以10,并计算这些值和ip_address值的不同组合。这样每个10秒的时间段分开计算。
如果你在样本数据上运行它,它会给你4条曲目,这就是你想要的。
尝试一下,看看它是否能为您提供完整数据集所需的结果:
SELECT COUNT(DISTINCT ip_address, FLOOR(time_stamp/10)) AS tracks
FROM tracking
答案 3 :(得分:0)
使用相同的ip和关闭时间对记录进行左连接,并过滤掉匹配的记录:
select count(*) as visits
from (
select t.ip_address
from tracking t
left join tracking t2
on t2.ip_address = t.ip_address
and t2.timestamp > t.timestamp and t2.timestamp <= t.timestamp + 10
where t2.ip_address is null
) x
答案 4 :(得分:0)
与SQL一样,有许多解决方案可以解决您的问题。 我会使用以下查询,这很简单,应该“足够好”:
SELECT COUNT(*) AS tracks
FROM (
SELECT ip_address
FROM tracking
GROUP BY ip_address, FLOOR(time_stamp / 10)
)
子查询以10秒的间隔对单个用户的访问进行分组,以便将它们计为一次访问。
原因是可以找到两次访问将出现在不同的10s窗口中的情况,即使这次访问之间的间隔小于10秒。它需要更复杂的逻辑来消除这种情况,并且这种增加的复杂性的分析值将是可疑的(无论如何,10s间隔听起来像一个任意值)。
答案 5 :(得分:0)
Select Z.IP, Count(*) As VisitCount
From (
Select V.IP
From visitors As V
Left Join visitors As V2
On V2.IP = V.IP
And V2.time_stamp > V.time_stamp
Group By V.IP, V.time_stamp
Having (Min(V2.time_stamp) - V.time_stamp) >= 10
) As Z
Group By Z.IP
这将计算下一个条目超过10秒作为新访问的任何访问。
答案 6 :(得分:0)
如果在前10秒内没有来自同一IP地址的前一条记录,则以下逻辑仅将访问计为“唯一访问”。
这意味着{1,11,21,32,42,52,62,72}将被视为2次访问,分别为3和5个曲目。
它通过首先识别唯一访问来实现此目的。然后它计算在该唯一访问和下一次独特访问之间发生的所有访问。
WITH
unique_visits
(
SELECT
ip_address, time_stamp
FROM
visitors
WHERE
NOT EXISTS (SELECT * FROM visitors AS [previous]
WHERE ip_address = visitors.ip_address
AND time_stamp >= visitors.timestamp - 10
AND time_stamp < visitors.timestamp)
)
SELECT
unique_visitors.ip_address,
unique_visitors.time_stamp,
COUNT(*) AS [total_tracks]
FROM
unique_visitors
INNER JOIN
visitors
ON visitors.ip_address = unique_visitors.ip_address
AND visitors.time_stamp >= unique_visitors.time_stamp
AND visitors.time_stamp < ISNULL(
(SELECT MIN(time_stamp) FROM unique_visitors [next]
WHERE ip_address = unique_visitors.ip_address
AND time_stamp > unique_visitors.ip_address)
, visitors.time_stamp + 1
)
您还需要(ip_address,time_stamp)
上的索引或主键答案 7 :(得分:0)
对于咯咯笑声来说,这是一个UPDATE hack,可以完成你需要的东西。有许多理由不实现这一点,包括但不限于它可能在某一天停止工作的事实。无论如何,假设您的表最初按ip排序 - >时间戳,这应该(通常)给你正确的答案。同样,这是为了完整性,如果您实现此功能,请查看up the risks beforehand。
CREATE TABLE #TestIPs
(
ip_address varchar(max),
time_stamp decimal(12,0),
cnt int
)
INSERT INTO #TestIPs (ip_address, time_stamp)
SELECT '180.2.79.3', 1301654105 UNION ALL
SELECT '180.2.79.3', 1301654106 UNION ALL
SELECT '180.2.79.3', 1301654354 UNION ALL
SELECT '180.2.79.3', 1301654356 UNION ALL
SELECT '180.2.79.3', 1301654358 UNION ALL
SELECT '180.2.79.3', 1301654366 UNION ALL
SELECT '180.2.79.3', 1301654368 UNION ALL
SELECT '180.2.79.3', 1301654422 UNION ALL
SELECT '180.2.79.4', 1301654105 UNION ALL
SELECT '180.2.79.4', 1301654106 UNION ALL
SELECT '180.2.79.4', 1301654354 UNION ALL
SELECT '180.2.79.4', 1301654356 UNION ALL
SELECT '180.2.79.4', 1301654358 UNION ALL
SELECT '180.2.79.4', 1301654366 UNION ALL
SELECT '180.2.79.4', 1301654368 UNION ALL
SELECT '180.2.79.4', 1301654422
DECLARE @count int; SET @count = 0
DECLARE @ip varchar(max); SET @ip = 'z'
DECLARE @timestamp decimal(12,0); SET @timestamp = 0;
UPDATE #TestIPs
SET @count = cnt = CASE WHEN time_stamp - @timestamp > 10 THEN @count + 1 ELSE CASE WHEN @ip <> ip_address THEN 1 ELSE @count END END,
@timestamp = time_stamp,
@ip = ip_address
SELECT ip_address, MAX(cnt) AS 'Visits' FROM #TestIPs GROUP BY ip_address
结果:
ip_address Visits
------------ -----------
180.2.79.3 3
180.2.79.4 3