mysql - 一段时间内的累计计数

标签 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']);

        }
    }

最佳答案

一个好的起点是

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

关于mysql - 一段时间内的累计计数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9376232/

相关文章:

php - 如何正确使用 mysql_connect() 和 mysql_select_db()?

mysql - 将 MySQL 数据库导入 SQL Server

mysql - SQL 仅选择列上具有最大值的行

sql - 如何在子查询结果上使用MAX()?

python - Pandas Dataframe Groupby 多列然后求和

mysql - 如何在 mysql 中使用 JOIN 语句实现以下目标?

mysql - 如何删除所有以某个前缀开头的MySQL表?

javascript - 我们可以将 Controller 中的 JSON 数据(MM/DD/YYYY 格式)与自定义过滤器中的今天日期进行比较,并在数组中显示过滤列表

mysql - 如何在MySQL中查找一年中的一月到七月缺少的月数

javascript - 在javascript中将日期转换为其他格式