使用Stack Overflow公共数据转储,我创建了三个简单的表:
问题表包含数十万行,其中Creation_Date从一年前到今天。查看数据,有两个值得注意的趋势:
如果这些因素都没有发挥作用,估计一个月内给定标签(或一组标签)的流量是相当简单的:
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字符串的标签,并吐出过去六个月对这些标签的页面浏览量。
更新在“获得”风滚草徽章之后,我认为是赏金的时候了!
答案 0 :(得分:5)
您需要考虑一个指数视图衰减曲线,类似于此 - http://en.wikipedia.org/wiki/Exponential_decay
我们需要的是曲线下面积达到所需时间(以天为单位)。
如果你做数学,你会得到一个结果
Views = V/λ[1 - e^(-λt)]
t(创建日期 - 今天的日期 - 1)
V是我们的观看次数
λ可以是2ln2 / T或1.4 / T
T可以是5天或7天的主要生命时间。让我们看看它。
我们在这里做了很多假设,因为SO的动态性质。但我很肯定它会带来不错的结果。
您现在要做的就是替换相应的值并获取视图。
答案 1 :(得分:2)
我想到了这种估算尾巴的方法:
获取标签列表, 对于这些标签中的每个问题 在creation_date之后的第一个月给出View_Count的80% 在creation_date之后的第二个月给出View_Count的10% 在截至今天的剩余月份之间平均分配10%
当然80%,10%只是我的选择,它们可以根据实际数据更精确地计算。此外,第二个月10%可能会被淘汰。所有这些逻辑都在:CASE WHEN diff ...
部分。
您获得估计的view_count / question / month
然后您所要做的就是每月总计view_count,如果您想要一个时间窗口,请在月份中添加条件
我创建了一个可以执行此操作的存储过程,但您必须首先创建一个临时表#tags(Tag_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
如果我使用以下数据运行此过程:
Question_Id View_Count Creation_Date tag_name
----------- ----------- ------------------------------ ----------
0 42 2009-09-10 00:00:00.000 sql
1 326 2008-08-04 00:00:00.000 sql
2 377 2008-08-04 00:00:00.000 sql
3 568 2008-08-03 00:00:00.000 sql
4 839 2008-08-01 00:00:00.000 sql
5 228 2009-03-01 00:00:00.000 sql
6 178 2009-03-11 00:00:00.000 sql
7 348 2009-08-11 00:00:00.000 c#
使用'sql'填充#tags
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#'填充#tags
GetTagViews '20090501', '20091001'
y m Views
----------- ----------- ----------------------------------------
2009 5 .000000000000
2009 6 .000000000000
2009 7 .000000000000
2009 8 278.000000000000
2009 9 35.000000000000
使用'sql'和&amp ;;填充#tags '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,c#)的峰值与2009-08赛季的(sql)比较,这是由于那个月被问到c#问题。)
N.B。:如果你总结详细的观点并与给定问题的原始数据进行比较,估计的结果会导致一些观点的差异(~1)!
答案 2 :(得分:0)
要模拟长尾,只需引入一个常量。或者使用对数函数。
your_formula(delta_t) + C
1 / (1 + log(1 + delta_t))
(省略系数)