我有一个图表,显示了基于IP组的独立访问者按日期(今天每小时)。
现在我想将这些数据根据IP和session_id分离到新访客和回访访客,并按日期(今天每小时)分组。我如何用SQL查询做到这一点?这可能吗?
查询应该在表中查找是否已经存在带有session_id的IP。那么它就是一个回头客。否则就是新访客。我不知道该怎么做。
查询我必须计算唯一的IP并按今天每小时对它们进行分组:
SELECT DISTINCT DATE_FORMAT(`date`, '%Y-%m-%d %H') as 'dates', COUNT(DISTINCT `ip`) as 'count' FROM `logging` WHERE DATE(date) = DATE(NOW()) GROUP BY `dates`
现在它显示我:
Dates Count
2021-02-04 00 10
2021-02-04 01 8
2021-02-04 02 5
等。
我要的是:
Dates Count new IP Count returning IP
2021-02-04 00 2 8
2021-02-04 01 4 4
2021-02-04 02 2 3
新IP:检查IP是否存储在只有一个已知session_id的表中。返回的IP:检查表中是否存储有多个不同的session_id
提前感谢!
UPDATE # 1:
现在我有以下查询来统计今天的回访人数:
SELECT date, ip, count(distinct ip, session_id) as 'count' FROM logging GROUP BY ip HAVING count > 1 AND date(date) = date(now())
结果例如:
date ip count (returning visitors)
2021-02-05 08:24:56 62.163.91.178 2
2021-02-05 10:24:15 77.163.91.223 6
2021-02-05 08:49:51 77.173.17.157 13
我如何改变这个查询按日期分组来得到这个?:
date count (returning visitors)
2021-02-05 08 15
2021-02-05 10 6
更新# 2:
多亏了Tsungur,我得到了以下查询,但每次运行它都会显示不同的结果。
select DATE_FORMAT([date], '%Y-%m-%d %H') as [date] , count(*) from ( SELECT [date], ip, count(distinct ip, session_id) as 'count' FROM logging GROUP BY ip HAVING count(distinct ip, session_id) > 1 AND date(date) = date(now())
) as sub
group by DATE_FORMAT([date], '%Y-%m-%d %H')
这里有一些数据可以使用:
ID session_id ip date
10752 454747k5k45l23h3b5n6k432nn 44.56.123.123 2021-01-01 09:15:54
10950 kmcoq3glgm187uhsfmo3r71h9q 86.85.131.246 2021-02-11 13:19:22
10958 kmcoq3glgm187uhsfmo3r71h9q 86.85.131.246 2021-02-12 12:10:52
10960 dfh78dfh7fdh7fdh6sd55dsd88 86.85.131.246 2021-02-12 13:00:02
10967 87s97sfh57sh6sh6s6sdsd44d3 11.56.873.560 2021-02-13 13:00:00
10968 rkdrgjsd7gjsd5jskjd46kjdsk 66.35.127.435 2021-02-13 13:01:00
10977 rkdrgjsd7gjsd5jskjd46kjdsk 66.35.127.435 2021-02-13 13:03:11
10978 dfajesj9sdj0dfh78sgd57sd5d 44.56.123.123 2021-02-13 13:05:12
10979 fhdf7f7hdf6fd44fdf3ffdf321 86.85.131.246 2021-02-13 14:05:02
10980 fhdf7f7hdf6fd44fdf3ffdf321 86.85.131.246 2021-02-13 14:06:13
以上数据应该告诉我:
date count (new visitor)
2021-02-13 13 2
2021-02-13 14 0
date count (returning visitor)
2021-02-13 13 1
2021-02-13 14 1
您可以通过对IP进行分组并过滤计数大于1的IP来查找返回的IP
SELECT [ip]
FROM [logging]
group by [ip]
having count(*)>1
那么你可以使用这个查询作为主查询的过滤器。
SELECT [ip], [date],count(*) as [Count]
FROM [logging]
where [ip] in
(
SELECT [ip]
FROM [logging]
group by [ip]
having count(*)>1
)
group by [ip],[date]
更新问题的最后一部分;
您当前的查询是一致的。您显示不同ip和会话的计数,但您的having子句没有反映这一点。您的Having子句按日期和ip分组计数。我不确定你是不是故意这么做的。也许你的"你有"条款应该是
having count(distinct ip, session_id)>1
。对于最终结果集,不修改最终查询,将其用作子查询,如
select DATE_FORMAT([date], '%Y-%m-%d %H') as [date] , count(*) from ( SELECT [date], ip, count(distinct ip, session_id) as 'count' FROM logging GROUP BY ip HAVING count > 1 AND date(date) = date(now()) ) as sub group by DATE_FORMAT([date], '%Y-%m-%d %H')
更新# 2首先是一些建议,如果可能的话,不要使用保留词作为列名(例如date)。我试图把这个问题分解。最后的查询看起来很脏,它可以被改进和缩短。但为了澄清问题,我使用了多个查询。你的第一个问题是计算唯一的sid和ip。为了简单起见(因为两者都是字符串),我使用sid+':'+ip作为一个唯一的字符串。另一个问题是对日期和时间进行分组。这里是一步一步的:
创建基本参考数据:
SELECT FORMAT(dt, 'yyyy-MM-dd HH') as dt_H, [sid]+':'+[ip] as uniq FROM [mytable] where cast(dt as date)=cast(getdate() as date)
根据我的唯一值和日期-小时查找返回的物品:
select dt_H, unique,count() as times from ()SELECT FORMAT(dt, 'yyyy-MM-dd HH') as dt_H, [sid]+':'+[ip] as unique从[mytable]其中cast(dt作为日期)=cast(getdate()作为日期))作为帮手group by dt_H, unique在计数()在1
如果您使用php,您可以稍后用:字符分隔唯一字段。但如果你想在sql中使用,我们将不区分列地连接主表:
select distinct return。dt_H,主要。(sid)主要。(ip),返回。从[mytable]作为主表的次数内连接(select dt_H,uniq,count(*) as times从(SELECT FORMAT(dt, 'yyyy-MM-dd HH') as dt_H,[sid]+':'+[ip] as uniq
FROM [mytable] where cast(dt as date)=cast(getdate() as date) ) as helper group by dt_H,uniq having count(*)>1
)作为返回returning.uniq =主。(sid) +":"+主要。[ip]和FORMAT(主)。dt, 'yyyy-MM-dd HH')=return . dt_h
你说你正在用PHP填补空白。您也可以在sql中这样做。我建议创建一个用户定义的函数(在很多时候会派上用场),它将在给定范围内创建数值:
CREATE FUNCTION [dbo].[GetNumbers](@Start int, @Stop int) RETURNS TABLE AS RETURN WITH Numbers (N) AS ( SELECT @Start UNION ALL SELECT @Start + N-@Start+1 FROM Numbers WHERE N < @Stop ) SELECT N FROM Numbers GO
用法:
SELECT N FROM [dbo].[GetNumbers] (0,23)
这将返回一个包含一天中所有小时的表。您可以将此表与日期部分和左连接结合使用以执行上述查询。因此,如果为null,则可以显示所有的小时数和返回时间的0。
PS:对不起,无法使格式化工作。