2017-02-28 134 views
0

晕倒大家。 我在不同的日期有不同客户的客户行为表。 我需要对这些客户进行月度报告,但其中一列应包括账户数量不等于零的客户数量。不同日子的累计和计数

我的表看起来是这样的:

CustomerID  Timestamp Amount 
5    1   100  
5    1   150 
10    1   20 
15    1   200 
15    1   -150 
5    2   -250  
10    2   50 
10    2   50 

从代码的输出应该

Timestamp  #Customers with sum(Amount)<>0 
1    3 
2    2 

由于所有3个账户在第一阶段正,但零客户5秒期。

到目前为止,我只设法为数据添加时间戳。

我的问题是,如何在任何时间段内累计每个客户的账户并计算这些账户不同于零的个案数量?

+0

这不是一个累计总和,这是一个按组计数。 – Shadow

+0

您可以在@vkp的答案中使用查询 –

回答

2

您可以通过相关子查询获得运行总和,并获得每个时间戳的不同客户的数量,其后总和为<> 0。

SELECT timestamp, 
    COUNT(DISTINCT customerid) AS count_customer 
FROM(
    SELECT customerid, 
     timestamp, 
     (
      SELECT SUM(amount) 
      FROM tablename t2 
      WHERE t2.customerid = t1.customerid 
      AND t2.timestamp <= t1.timestamp 
     ) AS cum_total 
FROM tablename t1 
) t 
WHERE cum_total <> 0 
GROUP BY timestamp; 

编辑:您可以尝试使用一个变量,看看它是否效果更好。

select timestamp,count(*) 
from (select customerid,timestamp 
     ,case when @customer=customerid then @cumsum:[email protected]+amount else @cumsum:=amount end as rsum 
     ,@customer:=customerid 
    from (select customerid,timestamp,sum(amount) as amount 
      from tablename 
      group by customerid,timestamp) t 
    join (select @cumsum:=0,@customer:='') c 
    order by customerid,timestamp 
    ) t 
where rsum<>0 
group by timestamp 
+0

代码运行,我确信它正在做正确的事情。不幸的是,它会在5分钟后停止,因为超过了允许的最长时间。这一定是由于您称为“tablename”的表格由5.960.000行组成。 那么还有其他更有效的方法吗? –

+0

查看使用变量获取运行总和的编辑。检查它是否更快。 –

0

你应该考虑使用group by条款

select Timestamp, count(customerID) as CustomersWithNonZeroAmount 
from tableName 
where Amount<>0 group by timestamp 

让我知道这是否正常工作。

1

另一种选择。

使用内部子查询来获取唯一的时间戳(如果您有一个这样的表,它可能会更有效率,因为它可以有效地使用索引)。它被连接到表格以获得当天或之前的所有行,并且使用HAVING来排除总和为负的那些数量。

然后,外部查询计算内部查询中每个时间戳返回的客户数量。

SELECT sub1.Timestamp, 
     COUNT(sub1.CustomerID) 
FROM 
( 
    SELECT sub0.Timestamp, a.CustomerID, SUM(a.Amount) AS amount_sum 
    FROM 
    ( 
     SELECT DISTINCT Timestamp 
     FROM amount_table 
    ) sub0 
    LEFT OUTER JOIN amount_table a ON sub0.Timestamp >= a.Timestamp 
    GROUP BY Timestamp, 
      CustomerID 
    HAVING amount_sum > 0 
) sub1 
GROUP BY Timestamp 

如果这可能会困难的是返回一个计数为0的行的时间戳,其中没有客户的积极金额达到该日期。可能不是你的问题,但如果它是: -

SELECT sub1.Timestamp, 
     SUM(IF(amount_sum > 0, 1, 0)) 
FROM 
( 
    SELECT sub0.Timestamp, a.CustomerID, SUM(a.Amount) AS amount_sum 
    FROM 
    ( 
     SELECT DISTINCT Timestamp 
     FROM amount_table 
    ) sub0 
    LEFT OUTER JOIN amount_table a ON sub0.Timestamp >= a.Timestamp 
    GROUP BY Timestamp, 
      CustomerID 
) sub1 
GROUP BY Timestamp