Postgresql查询返回一个月内发出超过1个订单的客户数量

时间:2014-08-07 06:46:26

标签: sql postgresql

所以我在我的代码中有这个查询:

        SELECT month, total_orders, first_orders, first_orders::numeric / total_orders::numeric * 100 AS ratio
        FROM (
          SELECT month, COUNT(1) AS total_orders
          FROM (
            SELECT DISTINCT date_trunc('month', date) AS month, email
            FROM shop_orders
            WHERE status_code = 'CONFIRMED'
          ) AS customers
          GROUP BY month
        ) AS total_orders_my_month

        LEFT JOIN (
          SELECT month, COUNT(1) AS first_orders FROM (
            SELECT email, date_trunc('month', MIN(date)) AS month
            FROM shop_orders
            WHERE status_code = 'CONFIRMED'
            GROUP BY email
          ) AS first_orders_by_month
          GROUP BY month
        ) AS first_orders_by_month2 USING (month)

        ORDER BY month DESC 

它的作用是以一种形式重新调整行:month |那个月的客户数量这个月的第一次客户数量首次购客的百分比

我需要的是每个月还能找到超过1个订单的客户数量。

所以我添加了这段代码:

        LEFT JOIN (
          SELECT month, COUNT(1) AS multiple_orders FROM (
            SELECT email, date_trunc('month', MIN(date)) AS month
            FROM shop_orders
            WHERE status_code = 'CONFIRMED'
            GROUP BY email HAVING COUNT(1) >=2
          ) AS multiple_orders_by_month
          GROUP BY month
        ) AS multiple_orders_by_month2 USING (month)

然而,这仅返回首次订购客户而非所有客户的2个或更多订单的客户。有人可以帮忙吗?

注意:所有数据都在shop_orders表中,唯一客户由电子邮件字段标识,日期字段包含有关订单日期的信息。

我希望它清楚。

我对postgresql很新,所以有人指向正确的方向吗?感谢。

1 个答案:

答案 0 :(得分:0)

我首先想指出的是,我是从纯SQL路线而不是postsgresql看这个,但理论基本相同。您的子查询SQL可能过于复杂,这是我正在研究如何创建查询:

首先,获取所有电子邮件地址的列表以及每月订购的订单数量;以下查询将返回分配给每封电子邮件的订单数量:

SELECT
    month
    , email
    , COUNT(*)
FROM
    shop_orders
WHERE
    status_code = 'Confirmed'
GROUP BY
    month
    , email

这将每个月返回每个电子邮件地址的订单计数。然后,您可以使用HAVING过滤器方法将此列表限制为每月包含多个电子邮件的所有电子邮件。

SELECT
    month
    , email
    , COUNT(*) as ordersThisMonth
FROM
    shop_orders
WHERE
    status_code = 'Confirmed'
GROUP BY
    month
    , email
HAVING
    COUNT(*) > 1

然后可以使用另一个聚合来访问此子查询,例如SUM(CASE WHEN ordersThisMonth > 1 THEN 1 ELSE 0 END),只有在收到多个订单时才会计算。我个人会尝试将您的查询简化为两个子查询,一个包含特定于month的详细信息,另一个包含monthemail的详细信息。

(以下代码未经语法检查,如前所述,我从纯粹的SQL角度来看这个。)

SELECT 
    month
    , total_orders
    , first_orders
    /* Add together all firstMonthCount entries as it should only be 1 for the customers first month */
    , SUM(firstMonthCount)::numeric / total_orders::numeric * 100 AS ratio
    /* Count only e-mails which have more than one order for the month */
    , SUM(CASE WHEN orderCount > 1 THEN 1 ELSE 0 END) AS multipleOrders
FROM 
    /*The following sub-query gets all the aggregates specific to a month */
    (   SELECT 
            date_trunc('month', date) AS month
            , COUNT(1) AS total_orders
        FROM 
            shop_orders
        WHERE 
            status_code = 'CONFIRMED'
        GROUP BY 
            month
    ) AS month_attributes
    /*The following sub-query gets all the aggregates specific to a month AND e-mail */
    LEFT JOIN (
        SELECT
            date_trunc('month', date) AS month
            , email
            , CASE WHEN date_trunc('month', date) = date_trunc('month', MIN(date)) THEN 1 ELSE 0 END AS firstMonthCount
            , COUNT(*) AS orderCount 
        FROM 
            shop_orders
        WHERE 
            status_code = 'CONFIRMED'
        GROUP BY 
            month
            ,email
    ) AS email_month_attributes USING (month)
GROUP BY 
    month

希望上述有关HAVING的查询和说明可以帮助您找到适合您目的的解决方案。我确信如果需要可读性/性能,可以进一步简化上述查询。