【问题标题】:MySQL Query Customers Who Have Not BoughtMySQL查询未购买的客户
【发布时间】:2020-06-26 13:36:24
【问题描述】:

背景:

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

示例:

Apple 希望在 3 月份赠送 1000 台 ipad。

他们希望每小时最多赠送 1 个。

他们希望将其提供给加利福尼亚或纽约的客户。

他们希望限制客户可以获得的免费 ipad 数量(每 15 天限制 1 个)。

数据结构:

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

  • ProductGiveAways

    • 产品 ID:AppleIpad
    • 数量:1000
    • 开始日期:03/01/2014
    • 结束日期 03/31/2014
    • 客户州:加利福尼亚,纽约
    • PurchaseLimitDays:15

问题:

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

我想不通的是最好的方法:

  1. 查询加利福尼亚或纽约的客户(这是连接和另一个表的好用例吗?)
  2. 当客户登录以查看哪些免费项目对他不可用时,如果客户已经获得此免费赠品,我如何排除 Apple iPad?

换句话说:

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

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

【问题讨论】:

  • 至少提供您已经完成的工作,您提议的数据库设计或 ERD。
  • 现在都在纸上。
  • 那么请帮我们一个忙 - 扫描并发布这些。我们无法通过射击黑暗来帮助您。至少张贴骨架结构,去除琐碎的细节。

标签: mysql sql filter


【解决方案1】:

我假设您将有一张桌子来存放已赠送的物品。在此表中,我将包含一个收件人 ID 列,该列可以映射回客户表。然后,您可以创建查询,通过搜索不符合取消资格条件的客户来查找符合条件的收件人。

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

【讨论】:

  • 在处理大型表时这对性能的影响有多大?是否和两次选择一样快?
  • 我已经使用了它,并没有注意到显着的影响。有很多变量,例如子查询的复杂性、表的索引方式以及会影响性能影响的“大”有多大。如果性能受到影响或存在问题,您也可以尝试使用“不存在”而不是“不在”。以下对不存在和不存在的问题进行了一些很好的讨论:stackoverflow.com/questions/2246772/…
【解决方案2】:

由于没有定义明确的数据结构,我将使用以下内容,您可以根据自己设计的任何数据结构进行调整:

  • 产品
    • ProductId - INTEGERIDENTITYPRIMARY KEY
    • 产品名称 - VARCHAR
  • 国家
    • StateId - INTEGERIDENTITYPRIMARY KEY
    • 州名 - VARCHAR
  • 客户
    • CustomerId - INTEGERIDENTITYPRIMARY KEY
    • StateId - INTEGER (FOREIGN KEY)
  • 促销
    • PromotionId - INTEGERIDENTITYPRIMARY KEY
    • ProductId - INTEGER (FOREIGN KEY)
    • 数量 - INTEGER
    • 开始日期 - DATETIME
    • 结束日期 - DATETIME
    • PurchaseLimitDays - INTEGER
  • 促销状态
    • PromotionId - INTEGER (FOREIGN KEY)
    • StateId - INTEGER (FOREIGN KEY)

所以回答你的问题:

查询加利福尼亚或纽约的客户(这是连接和另一个表的好用例吗?)

在上面的示例中,我个人会加入一个集中状态表 (PromotionState),我确信有更好的方法,但您可以执行以下条件:

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

或者你可以做一个GROUP BYHAVING,使用所有其他列作为GROUP BY的项目和类似HAVING COUNT * = 0HAVING SUM CASE WHEN (Conditions met) THEN 1 ELSE 0 END = 0的东西

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

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

正如我所说,您可以使用GROUP BYHAVING 来确定之前是否通过使用COUNTSUM 来“赢得”项目

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

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

【讨论】:

    【解决方案3】:

    一些数据库设计

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

    所以让我们重新组织你的域模型。

    状态 - 每个唯一状态 1 个条目 ...

    客户 - 每个唯一客户 1 个条目 StateId:(加利福尼亚|纽约|...) ...

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

    ProductGiveAways - 每个产品有很多条目 产品编号 数量 开始日期 结束日期 购买限制天数 ...

    ProductGiveAways_State ProductGiveAwaysId 状态标识 ...

    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
    

    【讨论】:

      【解决方案4】:

      对于 Laravel 我们使用类似这样的东西,我希望你可以关联这个查询,或者你可以使用在线 laravel 查询转换器在 mysql 中使用它(orator

      $user_id = auth()-&gt;user()-&gt;id;

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

      【讨论】:

        猜你喜欢
        • 2013-10-12
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2023-01-16
        • 2013-09-05
        • 1970-01-01
        相关资源
        最近更新 更多