Кумулятивный счет за время - PullRequest
0 голосов
/ 21 февраля 2012

У меня есть таблица заказов следующим образом:

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 ]

2 голосов
/ 21 февраля 2012

Хорошей отправной точкой является

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

Это даст вам дату_заказа, количество заказов на эту дату, количество клиентов на эту дату и список идентификаторов клиентов на эту дату.

Просто рассмотрим способ подсчета ежемесячно.Итак, взглянув вперёд, я использовал подзапрос для подсчета по ходу дела

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
0 голосов
/ 21 февраля 2012
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)
...