随着时间的推移累积计数

时间:2012-02-21 10:50:16

标签: mysql date aggregate-functions

我有这样的表格订单:

customer_id  order_date

10           2012-01-01
11           2012-01-02
10           2012-01-02
12           2012-01-03
11           2012-01-04

12           2012-02-01
11           2012-02-04
13           2012-02-05
14           2012-02-06

如何获得这样的累计平均值(每月):

order date   count orders    count customers   (customer_id)
2012-01      1               1                 (12)
2012-01      2               2                 (10,11)
2012-02      1               2                 (13,14)
2012-02      2               2                 (10,12
2012-02      3               2                 (11)

显示客户数量与每位客户的订单数量随时间的变化情况。

以下查询为我提供了所需信息 - 但不是随着时间的推移。如何随着时间的推移迭代查询?

SELECT number_of_orders, count(*) as amount FROM (
 SELECT o.customer_id, count(*) as number_of_orders
   FROM orders o
 GROUP BY o.customer_id) as t1
GROUP BY number_of_orders

更新

现在已经构建了以下PHP代码来生成我需要的东西,想知道是否可以使用像http://www.freeopenbook.com/mysqlcookbook/mysqlckbk-chp-12-sect-14.html

这样的累积计数来完成
    $year = 2011;
    for ($cnt_months = 1; $cnt_months <= 12; $cnt_months++) {
        $cnt_months_str = ($cnt_months < 10) ? '0'.$cnt_months : $cnt_months;
        $raw_query = "SELECT number_of_orders, count(*) as amount
              FROM (
                SELECT
                o.customer_id,
                count(*) as number_of_orders
                FROM orders o
                 where Date_Format( o.order_date, '%Y%m' ) >= " . $year . "01 and Date_Format( o.order_date, '%Y%m' ) <= " . $year . $cnt_months_str . "
                GROUP BY o.customer_id) as t1
              GROUP BY number_of_orders";

        $query = db_query($raw_query);
        while ($row = db_fetch_array($query)) {
            $data[$cnt_months_str][$row['number_of_orders']] = array($row['number_of_orders'], (int)$row['amount']);

        }
    }

2 个答案:

答案 0 :(得分:2)

一个很好的起点是

SELECT
    order_date,
    COUNT(*) AS distinctOrders,
    COUNT(DISTINCT customer_id) AS distinctCustomers,
    GROUP_CONCAT(DISTINCT customer_id ASC) AS customerIDs
FROM orders

GROUP BY order_date ASC

这将为您提供order_date,该日期的订单数量,该日期的客户数量以及该日期的客户ID列表。

只是看一个逐月统计的方法。因此,为了实现这一目标,我已经使用了一个子查询来计算它的结果

SELECT 
    ordersPerDate.*,
    IF(
        MONTH(ordersPerDate.order_date)=@thisMonth,
        @runningTotal := @runningTotal+ordersPerDate.distinctOrders,
        @runningTotal := 0
    ) AS ordersInThisMonth,
    @thisMonth := MONTH(ordersPerDate.order_date)
FROM
(
    SELECT
    @thisMonth := 0,
    @runningTotal := 0
) AS variableInit,
(
    SELECT
        order_date,
        COUNT(*) AS distinctOrders,
        COUNT(DISTINCT customer_id) AS distinctCustomers,
        GROUP_CONCAT(DISTINCT customer_id ASC) AS customerIDs
    FROM orders

    GROUP BY order_date ASC
) AS ordersPerDate

最后要清理它,将它包装在另一个子查询中,只是为了返回所需的行而不是内部变量

在个别日子分组

SELECT 
    collatedData.order_date,
    collatedData.ordersInThisMonth AS count_orders,
    collatedData.distinctCustomers AS count_customers,
    collatedData.customerIDs AS customer_ids
FROM (

    SELECT 
        ordersPerDate.*,
        IF(
            MONTH(ordersPerDate.order_date)=@thisMonth,
            @runningTotal := @runningTotal+ordersPerDate.distinctOrders,
            @runningTotal := 0
        ) AS ordersInThisMonth,
        @thisMonth := MONTH(ordersPerDate.order_date)
    FROM
    (
        SELECT
        @thisMonth := 0,
        @runningTotal := 0
    ) AS variableInit,
    (
        SELECT
            order_date,
            COUNT(*) AS distinctOrders,
            COUNT(DISTINCT customer_id) AS distinctCustomers,
            GROUP_CONCAT(DISTINCT customer_id) AS customerIDs
        FROM orders

        GROUP BY order_date ASC
    ) AS ordersPerDate
) AS collatedData

现在最后,根据OP的最新产品

获取更多信息

按日历月分组

// Top level will sanitise the output
SELECT 
    collatedData.orderYear,
    collatedData.orderMonth,
    collatedData.distinctOrders,
    collatedData.ordersInThisMonth AS count_orders,
    collatedData.distinctCustomers AS count_customers,
    collatedData.customerIDs AS customer_ids
FROM (
    // This level up will iterate through calculating running totals
    SELECT 
        ordersPerDate.*,
        IF(
            (ordersPerDate.orderYear,ordersPerDate.orderMonth) = (@thisYear,@thisMonth),
            @runningTotal := @runningTotal+ordersPerDate.distinctOrders*ordersPerDate.distinctCustomers,
            @runningTotal := 0
        ) AS ordersInThisMonth,
        @thisMonth := ordersPerDate.orderMonth,
        @thisYear := ordersPerDate.orderYear
    FROM
    (
        SELECT
        @thisMonth := 0,
        @thisYear := 0,
        @runningTotal := 0
    ) AS variableInit,
    (
        // Next level up will collate this to get per year, month, and per number of orders
        SELECT
            ordersPerDatePerUser.orderYear,
            ordersPerDatePerUser.orderMonth,
            ordersPerDatePerUser.distinctOrders,
            COUNT(DISTINCT ordersPerDatePerUser.customer_id) AS distinctCustomers,
            GROUP_CONCAT(ordersPerDatePerUser.customer_id) AS customerIDs
        FROM (
            // Inner query will get the number of orders for each year, month, and customer
            SELECT
                YEAR(order_date) AS orderYear,
                MONTH(order_date) AS orderMonth,
                customer_id,
                COUNT(*) AS distinctOrders
            FROM orders
            GROUP BY orderYear ASC, orderMonth ASC, customer_id ASC
        ) AS ordersPerDatePerUser
        GROUP BY  
            ordersPerDatePerUser.orderYear ASC,  
            ordersPerDatePerUser.orderMonth ASC, 
            ordersPerDatePerUser.distinctOrders DESC
    ) AS ordersPerDate


) AS collatedData

答案 1 :(得分:0)

SELECT
  substr(order_date,1,7) AS order_period,
  count(*) AS number_of_orders,
  count(DISTINCT orders.customer_id) AS number_of_customers,
  GROUP_CONCAT(DISTINCT orders.customer_id) AS customers
FROM orders
GROUP BY substr(order_date,1,7)