MySQL查询未购买的客户

时间:2014-02-12 02:50:46

标签: mysql sql filter

背景:

我们正在设立促销系统,向注册客户赠送免费产品。我们正在尝试设计一个足够灵活的数据库来处理多种产品和赠品。要求是产品可以先到先得的方式送给合格的客户。

示例:

Apple希望在3月份放弃1000个ipads。他们想要每小时最多赠送1个。他们希望将它交给位于加利福尼亚州或纽约州的客户。他们希望限制客户可以获得的免费ipads数量(每15天限制1个)。

数据结构:

  • 产品 - 每个独特产品1个条目。例如Apple iPad

  • ProductGiveAways

    • ProductID:AppleIpad
    • 数量:1000
    • StartDate:03/01/2014
    • 截止日期03/31/2014
    • CustomerState:California,NewYork
    • PurchaseLimitDays:15

问题:

通过上述结构,我们可以对客户表进行查询,并找出哪些资格适合促销。

我无法弄清楚最好的方法:

  1. 查询加利福尼亚州或纽约州的客户(这是一个很好的用例,用于连接和另一个表吗?)
  2. 当客户登录以查看他无法使用哪些免费物品时,如果客户已经获得此免费赠品,我该如何排除Apple iPad?
  3. 换句话说:

    • 说amazon.com想给我看一些我还没买过的DVD。查询的正确方法是什么?

    • 首先获取以前购买的产品列表然后使用NOT子句查询是正确的方法吗?

4 个答案:

答案 0 :(得分:2)

我假设你已经找到了一张桌子。在此表中,我将包含一个可以映射回customer表的收件人ID列。然后,您可以通过搜索未达到取消资格条件的客户来创建查询以查找符合条件的收件人。

select customerid 
from customer
where customerid not in (
                          select recipientid
                          from givenaway
                          where ..... and ....
                         )

答案 1 :(得分:1)

因为没有定义明确的数据结构,所以我将使用以下内容,您可以根据自己设计的数据结构进行定制:

  • 产品
    • ProductId - INTEGERIDENTITYPRIMARY KEY
    • ProductName - VARCHAR
    • StateId - INTEGERIDENTITYPRIMARY KEY
    • 州名称 - VARCHAR
  • <强>客户
    • CustomerId - INTEGERIDENTITYPRIMARY KEY
    • StateId - INTEGERFOREIGN KEY
  • 促进
    • PromotionId - INTEGERIDENTITYPRIMARY KEY
    • ProductId - INTEGERFOREIGN KEY
    • 数量 - INTEGER
    • StartDate - DATETIME
    • 结束日期 - DATETIME
    • PurchaseLimitDays - INTEGER
  • PromotionState
    • PromotionId - INTEGERFOREIGN KEY
    • StateId - INTEGERFOREIGN KEY

所以回答你的问题:

  

查询加利福尼亚州或纽约州的客户(对于加入和另一个表来说,这是一个很好的用例吗?)

就我个人而言,我会在上面的例子中加入一个集中的状态表(PromotionState),我确信有更好的方法,但你可以做一个如下的条件:

WHERE  
    (SELECT COUNT * FROM PromotionState x WHERE x.PromotionId = p.PromotionId) = 0
    OR NOT(ps.PromotionId IS NULL)

或者,您可以使用所有其他列作为GROUP BY的项目以及类似HAVINGGROUP BY HAVING COUNT * = 0和HAVING SUM CASE WHEN (Conditions met) THEN 1 ELSE 0 END = 0 p>

  

当客户登录以查看他无法使用哪些免费物品时,如果客户已经获得此免费赠品,我该如何排除Apple iPad?

     

假设amazon.com想要向我展示我尚未购买的DVD。查询的正确方法是什么?

正如我所说,您可以使用GROUP BYHAVING来确定某个项目之前是否已使用COUNTSUM

  

首先获取先前购买的产品列表,然后使用NOT子句查询是正确的方法吗?

可能有更好的方法,子查询会变得非常沉重和缓慢,我建议尝试上述一些技术,然后使用分析器来提高效率。

答案 2 :(得分:0)

一些数据库设计

首先,当您将CustomerState设置为California,NewYork时,您违反了数据库设计的First Normal Form

因此,让我们重新组织您的域模型。

- 每个唯一身份1个条目 ...

客户 - 每位唯一客户输入一次 StateId :(加利福尼亚州|纽约州| ...) ...

产品 - 每个独特产品1个条目 ...

ProductGiveAways - 每个产品有很多条目 产品ID 数量 开始日期 结束日期 PurchaseLimitDays ...

<强> ProductGiveAways_State ProductGiveAwaysId STATEID ...

Customer_Product - 客户每次购买产品1次 顾客ID 产品编号 购买日期 ...

技术问题

如果您想查询加利福尼亚州或纽约州的客户,您现在需要做的就是:

// This is just an example, you have to change the 'California', 'New York' with their ids
SELECT * FROM Customer WHERE StateId IN ('California', 'New York')

当客户登录以查看可供他使用的免费物品时:

// It's not an accurate sql, just an example
SELECT Product.* 
FROM Product 
JOIN ProductGiveAways ON ProductId
JOIN ProductGiveAways_State ON ProductGiveAwaysId
WHERE ProductId NOT IN (
    SELECT ProductId FROM Customer_Product JOIN ProductGiveAways ON ProductId
    WHERE CustomerId = /* the customer id */
    AND ( TO_DAYS(now()) - TO_DAYS(PurchaseDate) ) < PurchaseLimitDays
) 
AND StateId = /* customer StateId */
AND StartDate < now() < End Date // Elligible ProductGiveAways

答案 3 :(得分:0)

对于Laravel,我们使用类似的方法,我希望您可以与此查询相关,也可以使用在线laravel查询转换器在mysql( orator )中使用它

$user_id = auth()->user()->id;

Product::where('status', 'active')
->whereNotIn('id', function($query) use ($user_id) {
$query->select('product_id')->from(new OrderProduct->getTable())
->where('user_id', $user_id)->where('status', 'delivered');
});