计算两个变量的平均值

时间:2014-04-04 20:25:31

标签: sql teradata

我有一张如下表格:

VisitorID   Product         VisitDayBeforePurchase
1           Product1            0
2           Product2            1
3           Product3            2
1           Product1            2
3           Product2            2
3           Product3            2

VisitorID始终是每个访问者唯一的,visitDayBeforePurchase代表他们是否在购买前x天来到网站。我想做的是制作一个可以将表格转换成这样的语句的语句。

 Product   Day0   Day1  Day2
 Product1   1      0     1
 Product2   0      1     2
 Product3   0      0     2

基本上,我希望在购买特定产品前X天看到有人访问网站的平均访问次数。即访问前每天每件产品的总和(访问)/总和(uniqueVisitors)

我只是要从表1下载数据并编写一个脚本来计算,但我想知道是否有办法在SQL中执行此操作。

如果有人能指出我正确的方向,我们将不胜感激。

1 个答案:

答案 0 :(得分:1)

对于已知数量的列,您描述的表 - 实际上不是平均值,它是计数 - 可以使用IF来完成:

SELECT Product,
       SUM(IF(VisitDayBeforePurchase = 0, 1, 0)) AS Day0,
       SUM(IF(VisitDayBeforePurchase = 1, 1, 0)) AS Day1,
       SUM(IF(VisitDayBeforePurchase = 2, 1, 0)) AS Day2
FROM yourtable
GROUP BY Product;
  

基本上,我希望在购买特定产品前X天看到有人访问网站的平均访问次数。即访问前每天每件产品的总和(访问)/总和(uniqueVisitors)

这是一个不同的请求。您可以通过添加(或替换)列

来完成此操作
SELECT Product,
       AVG(VisitDayBeforePurchase) AS AverageDays
FROM yourtable
GROUP BY Product;

这会给你所有(你可以看到它在行动中here)。

SELECT Product,
       SUM(IF(VisitDayBeforePurchase = 0, 1, 0)) AS Day0,
       SUM(IF(VisitDayBeforePurchase = 1, 1, 0)) AS Day1,
       SUM(IF(VisitDayBeforePurchase = 2, 1, 0)) AS Day2,
       AVG(VisitDayBeforePurchase) AS AverageDays
FROM yourtable
GROUP BY Product;

会计多个访客

简而言之:它很复杂,也许它最好不要完成

假设我们有一个产品被同一个访问者两次(或更多)查看,那么我们不希望将它们视为单独访问。如果先生。 X在三天,两天和购买当天访问了该网站,我们该怎么做?

乍一看,我们可能会认为只计算最后次访问。但是我们会得到明显的意外后果:因为您必须访问该网站以在网站上购买商品,然后上次访问才能购买您进行购买的访问< / em>,所以它总是在购买之前的零天。在同一时间和分钟,甚至可能。虽然可以考虑上次访问,但它会给我们带来毫无价值的结果。

考虑到第一次访问也会产生忽视重复购买的意外后果,因此我们的最佳重复客户实际上将被视为最顽固和优柔寡断。< / p>

因此,人们必须考虑,例如,只有实际用SUM表格的日间隔,然后做某事:

VisitorID       ProductID       VDBeforeP
42              137             3
42              137             2
41              137             2

要做什么?如果我们只考虑访问者42的一个记录,无论我们做什么,我们最终得出的结果都是错误的,要么平均过于乐观,要么平均过于悲观。我们可以考虑用户42的平均值,对于权重 1 (而不是 2 )的用户42,它会给出2.5,所以相比之下与#34;粗暴的平均值&#34; (上面的解决方案)我们认为重复的客户少一点。

为此,我们使用SUBSELECT:我们获取每个数据点只有一个访客和产品的平均数据

SELECT VisitorID, Product, AVG(VisitDayBeforePurchase) AS VisitDayBeforePurchase
    FROM visits GROUP BY VisitorID, Product;

这将生成一个格式与原始格式相同的表格,但具有平均数据。 它永远不会起作用因为原始查询只验证了整数天数,而2.5既不是2也不是3.所以我们必须做出乐观或悲观的修正;这是乐观的

SELECT VisitorID, Product, FLOOR(AVG(VisitDayBeforePurchase)) AS VisitDayBeforePurchase
    FROM visits GROUP BY VisitorID, Product;

虽然悲观会使用FLOOR(1.0+AVG...。折衷方案是使用ROUND

现在我们重复查询:

SELECT Product,
    SUM(IF(V = 0, 1, 0)) AS Day0,
    SUM(IF(V = 1, 1, 0)) AS Day1,
    SUM(IF(V = 2, 1, 0)) AS Day2,
    AVG(BetterV) AS AverageDays
FROM (
    SELECT VisitorID,
           Product,
           ROUND(AVG(VisitDayBeforePurchase)) AS V,
           AVG(VisitDayBeforePurchase) AS BetterV
    FROM visits GROUP BY VisitorID, Product
) AS grouped
  GROUP BY Product;

<强> A working example can be also found here

地图,减少

要在map-reduce环境中运行上述内容,您需要两个阶段:直接输出VisitorID,Product和VisitDayBeforePurchase的map阶段,以及按键分组的reduce阶段(VisitorID,Product)并输出那些和V (和BetterV?)计算结果。

这会被送到一个新的减少阶段,该阶段在V&#39上执行平均值。