根据新的和返回的细分购买

时间:2010-11-22 21:46:58

标签: sql mysql

我正在尝试编写一个可以选择特定日期的查询,并计算这些客户之前已下订单的数量以及新订单数量。为简单起见,这是表格布局:

id (auto) | cust_id | purchase_date
-----------------------------------  
1         | 1       | 2010-11-15  
2         | 2       | 2010-11-15  
3         | 3       | 2010-11-14  
4         | 1       | 2010-11-13  
5         | 3       | 2010-11-12  

我试图按日期选择订单,然后加入之前日期相同user_id上的所有先前订单,然后计算订单数量,以及订购数量。这是我失败的尝试:

SELECT SUM( 
CASE WHEN id IS NULL 
THEN 1 
ELSE 0 
END ) AS new, SUM( 
CASE WHEN id IS NOT NULL 
THEN 1 
ELSE 0 
END ) AS returning
FROM (

SELECT o1 . * 
FROM orders AS o
LEFT JOIN orders AS o1 ON ( o1.user_id = o.user_id
AND DATE( o1.created ) =  "2010-11-15" ) 
WHERE DATE( o.created ) <  "2010-11-15"
GROUP BY o.user_id
) AS t

3 个答案:

答案 0 :(得分:3)

鉴于参考数据(2010-11-15),我们对在该日期下订单的不同客户的数量感兴趣(A),我们感兴趣的是有多少客户先前下了订单(B),有多少没有(C)。显然,A = B + C.

Q1:在参考日期

下的订单数量
SELECT COUNT(DISTINCT Cust_ID)
  FROM Orders
 WHERE Purchase_Date = '2010-11-15';

Q2:在参考日期下订单的客户列表

SELECT DISTINCT Cust_ID
  FROM Orders
 WHERE Purchase_Date = '2010-11-15';

Q3:在

之前订购的参考日期下订单的客户列表
SELECT DISTINCT o1.Cust_ID
  FROM Orders AS o1
  JOIN (SELECT DISTINCT o2.Cust_ID
          FROM Orders AS o2
         WHERE o2.Purchase_Date = '2010-11-15') AS c1
    ON o1.Cust_ID = c1.Cust_ID
 WHERE o1.Purchase_Date < '2010-11-15';

Q4:在

之前订购的参考数据下订单的客户数量
SELECT COUNT(DISTINCT o1.Cust_ID)
  FROM Orders AS o1
  JOIN (SELECT DISTINCT o2.Cust_ID
          FROM Orders AS o2
         WHERE o2.Purchase_Date = '2010-11-15') AS c1
    ON o1.Cust_ID = c1.Cust_ID
 WHERE o1.Purchase_Date < '2010-11-15';

Q5:结合Q1和Q4

有几种方法可以进行组合。一种是在选择列表中使用Q1和Q4作为(复杂)表达式;另一种方法是将它们用作FROM子句中的表,它们之间不需要连接,因为每个表都是可以在笛卡尔积中连接的单行单列表。另一个是UNION,其中每一行都用它计算的内容进行标记。

SELECT (SELECT COUNT(DISTINCT Cust_ID)
          FROM Orders
         WHERE Purchase_Date = '2010-11-15') AS Total_Customers,
       (SELECT COUNT(DISTINCT o1.Cust_ID)
          FROM Orders AS o1
          JOIN (SELECT DISTINCT o2.Cust_ID
                  FROM Orders AS o2
                 WHERE o2.Purchase_Date = '2010-11-15') AS c1
            ON o1.Cust_ID = c1.Cust_ID
         WHERE o1.Purchase_Date < '2010-11-15') AS Returning_Customers
  FROM Dual;

(我很高兴地假设MySQL有一个DUAL表 - 类似于Oracle。如果没有,创建一个包含单行数据的单个列的表是微不足道的。 Update 2 :抨击MySQL 5.5 Manual表明支持'FROM Dual'但不需要;没有FROM子句,MySQL很高兴。)

更新1 :在关键位置添加限定符'o1.Cust_ID',以避免评论中显示的“模糊列名称”。

答案 1 :(得分:1)

怎么样

SELECT * FROM
  (SELECT * FROM 
    (SELECT CUST_ID, COUNT(*) AS ORDER_COUNT, 1 AS OLD_CUSTOMER, 0 AS NEW_CUSTOMER
       FROM ORDERS
       GROUP BY CUST_ID
       HAVING ORDER_COUNT > 1)
  UNION ALL
    (SELECT CUST_ID, COUNT(*) AS ORDER_COUNT, 0 AS OLD_CUSTOMER, 1 AS NEW_CUSTOMER
       FROM ORDERS
       GROUP BY CUST_ID
       HAVING ORDER_COUNT = 1)) G
  INNER JOIN
    (SELECT CUST_ID, ORDER_DATE
       FROM ORDERS) O
    USING (CUST_ID)
  WHERE ORDER_DATE = [date of interest] AND
        OLD_CUSTOMER = [0 or 1, depending on what you want] AND
        NEW_CUSTOMER = [0 or 1, depending on what you want]

不确定这是否会完成所有事情,但它可能会提供一个起点。

分享并享受。

答案 2 :(得分:1)

select count(distinct o1.cust_id) as repeat_count, 
       count(distinct o.cust_id)-count(distinct o1.cust_id) as new_count
    from orders o
        left join (select cust_id
                       from orders
                       where purchase_date < "2010-11-15"
                       group by cust_id) o1
            on o.cust_id = o1.cust_id
    where o.purchase_date = "2010-11-15"