Sql 在数据有限的情况下,每个标签(或标签组)每月的大致页面浏览量?
使用堆栈溢出公共数据转储,我创建了三个简单的表: 问题问题Id、视图计数、创建日期 标签标签名称 问题标签问题Id,标签名称 问题表有数十万行,创建日期从一年前到今天。纵观数据,有两个显著趋势: 问题的数量随着时间的推移而增加——例如,本月提出的问题比三个月前多 问题视图有一条长尾——通过查看基于开放周的视图,我们可以看到大多数问题视图出现在第一周;第二次和第三次的数额较小;在接下来的几周里,它会有一条长长的尾巴 如果这两个因素都不起作用,那么估计一个月内给定标签或一组标签的流量就相当简单了:Sql 在数据有限的情况下,每个标签(或标签组)每月的大致页面浏览量?,sql,sql-server,tsql,Sql,Sql Server,Tsql,使用堆栈溢出公共数据转储,我创建了三个简单的表: 问题问题Id、视图计数、创建日期 标签标签名称 问题标签问题Id,标签名称 问题表有数十万行,创建日期从一年前到今天。纵观数据,有两个显著趋势: 问题的数量随着时间的推移而增加——例如,本月提出的问题比三个月前多 问题视图有一条长尾——通过查看基于开放周的视图,我们可以看到大多数问题视图出现在第一周;第二次和第三次的数额较小;在接下来的几周里,它会有一条长长的尾巴 如果这两个因素都不起作用,那么估计一个月内给定标签或一组标签的流量就相当简单了:
SELECT YEAR(Q.Creation_Date)
,MONTH(Q.Creation_Date)
,SUM( Q.View_Count / DATEDIFF(m,Q.Creation_Date,GETDATE()) )
FROM Questions Q
JOIN QuestionTags QT
ON Q.Question_Id = QT.Question_Id
WHERE QT.Tag_Name IN ('c#','.net', ... )
GROUP BY YEAR(Q.Creation_Date), MONTH(Q.Creation_Date)
ORDER BY 1,2
但由于上述因素,尤其是长尾,我不确定如何近似视图。我的想法是创建一个函数,使用长尾公式,根据当前的视图数和打开的周数计算一个月的视图
下面是我找到尾巴的方法:
DECLARE @SDTE DATETIME, @EDTE DATETIME
SELECT @SDTE = '2009-01-11' -- after new years holiday
,@EDTE = CAST( MAX([Creation_Date]) AS INT )
FROM [Questions]
SELECT [DaysOpen_Count]
,AVG( [WView_Count] )
FROM
(
SELECT QT.[Tag_Name],
Q.[View_Count],
[DaysOpen_Count] = DATEDIFF(DAY, Q.[Creation_Date], @EDTE),
[WView_Count] = CAST( Q.[View_Count] / ( DATEDIFF(DAY, Q.[Creation_Date], @EDTE) / 7.0 ) AS INT )
FROM [Questions] Q
INNER JOIN [QuestionTags] QT
ON Q.[Question_Id] = QT.[Question_Id]
WHERE [Tag_Name] IN ('c#','.net',...)
AND [Creation_Date] < @EDTE
) Q
GROUP BY [DaysOpen_Count]
ORDER BY 1,2
如何继续创建此SQL查询
最终目标是一个存储过程,它输入一个CSV标签字符串,并为这些标签显示过去六个月的页面视图
获得风滚草徽章后,我想是时候赏金了 我想到了这种估算尾部的方法:
DECLARE @SDTE DATETIME, @EDTE DATETIME
SELECT @SDTE = '2009-01-11' -- after new years holiday
,@EDTE = CAST( MAX([Creation_Date]) AS INT )
FROM [Questions]
SELECT [DaysOpen_Count]
,AVG( [WView_Count] )
FROM
(
SELECT QT.[Tag_Name],
Q.[View_Count],
[DaysOpen_Count] = DATEDIFF(DAY, Q.[Creation_Date], @EDTE),
[WView_Count] = CAST( Q.[View_Count] / ( DATEDIFF(DAY, Q.[Creation_Date], @EDTE) / 7.0 ) AS INT )
FROM [Questions] Q
INNER JOIN [QuestionTags] QT
ON Q.[Question_Id] = QT.[Question_Id]
WHERE [Tag_Name] IN ('c#','.net',...)
AND [Creation_Date] < @EDTE
) Q
GROUP BY [DaysOpen_Count]
ORDER BY 1,2
要查看标签列表,
对于这些标签中的每个问题
给出创建日期后的第一个月视图计数的80%
在创建日期后的第二个月,提供视图计数的10%
在今天之前的剩余月份平均分摊10%
当然,80%,10%只是我的选择,它们可以根据实际数据更精确地计算。此外,第二个月的10%可能会被取消。所有的逻辑都是这样的:当差异。。。部分
您可以获得估计的查看次数/问题/月份
然后,您所要做的就是每月查看和计数,如果您想要一个时间窗口,请在该月添加一个条件
我创建了一个可以执行此操作的存储过程,但是您必须首先创建一个临时表tagsTag_name,在其中放置所需的标记
CREATE PROCEDURE GetTagViews @startDate datetime, @endDate datetime
As
IF exists (SELECT null FROM sysobjects WHERE name = '#months' and type = 'U')
DROP TABLE #MONTHS
CREATE TABLE #MONTHS
(
month datetime
)
DECLARE @currMonth datetime
SELECT @currMonth = MIN(Creation_Date) FROM Questions
-- Populate #MONTHS with all the months from the oldest
-- question creation_date to Today
WHILE @currMonth < getdate()
BEGIN
-- insert date starting at the beginning og the month
INSERT INTO #MONTHS select @currMonth - day(@currMonth) + 1
SELECT @currMonth = dateadd(m, 1, @currMonth) -- advance 1 month
END
SELECT YEAR(month) y, MONTH(month) m, SUM(curr_month_views) Views FROM (
SELECT Q1.month, Q1.diff, round(
CASE WHEN diff = dmin and diff = dmax THEN View_Count
WHEN diff = dmin and diff < dmax THEN 0.8*View_Count
WHEN diff = dmin+1 and diff < dmax THEN 0.1*View_Count
WHEN diff = dmin+1 and diff = dmax THEN 0.2*View_Count
WHEN diff >= dmin+2 THEN 0.1/(dmax - (dmin+2) + 1)*View_Count
ELSE 0
END, 0) curr_month_views
FROM (
SELECT Q.question_id, m.month,
DATEDIFF(m, Q.Creation_Date, m.month) diff,
Q.View_Count, dmin, dmax
FROM Questions Q,
#MONTHS m,
(SELECT MIN(DATEDIFF(m, Q.Creation_Date, m.month)) [dmin],
MAX(DATEDIFF(m, Q.Creation_Date, m.month)) [dmax]
FROM Questions Q,#MONTHS m
WHERE DATEDIFF(m, Q.Creation_Date, m.month) >= 0) MINMAX
) Q1 join QuestionTags QT on Q1.question_id = QT.question_id
join #tags on #tags.Tag_Name = QT.Tag_Name
) b WHERE month >= @startDate - day(@startDate) + 1
AND month <= @enddate - day(@enddate) + 1
GROUP BY Year(month), Month(month)
ORDER BY 1, 2
用“sql”填充标记
GetTagViews '20090501', '20091001'
y m Views
----------- ----------- ---------------
2009 5 21.000000000000
2009 6 21.000000000000
2009 7 21.000000000000
2009 8 21.000000000000
2009 9 55.000000000000
用“c”填充标记
GetTagViews '20090501', '20091001'
y m Views
----------- ----------- ----------------------------------------
2009 5 .000000000000
2009 6 .000000000000
2009 7 .000000000000
2009 8 278.000000000000
2009 9 35.000000000000
用“sql”和“c”填充标记
GetTagViews '20090501', '20091001'
y m Views
----------- ----------- ----------------
2009 5 21.000000000000
2009 6 21.000000000000
2009 7 21.000000000000
2009 8 299.000000000000
2009 9 90.000000000000
你可以看到sql的峰值,与2009-08年唯一的sql相比,这是因为那个月被问到了c问题
注:如果你总结了详细的观点,并与给定问题的原始数据进行比较,我的估算结果会导致某些观点的差异~1>P>你需要考虑一个指数图衰减曲线,类似于这个—— 这里我们需要的是曲线下的面积,直到所需的时间(以天为单位) 如果你算一下,就会得出一个结果
Views = V/λ[1 - e^(-λt)]
t是创建日期-今天的日期-1
V是我们的浏览量
λ可以是2ln2/T或1.4/T
T可以是一个主要的生命周期,如5天或7天。我们就买它吧
我们在这里做了很多假设,因为SO是动态的。但我肯定它会产生好的结果
您现在所要做的就是替换适当的值并获取视图。要模拟长尾巴,只需引入一个常量。或者使用对数函数
your_formula(delta_t) + C
1 / (1 + log(1 + delta_t))
系数被省略这看起来非常接近我想要的;至于动态性。。。所有这些都是平均值,特别是当我们放弃一些奇怪的问题,比如你可能需要微调公式,特别是V和衰变率λ。此类问题的衰减率非常低,为1/25?。