簡體   English   中英

未購買的 MySQL 查詢客戶

[英]MySQL Query Customers Who Have Not Bought

背景:

我們正在建立一個促銷系統,向注冊客戶贈送免費產品。 我們正在嘗試設計一個足夠靈活的數據庫來處理多種產品和贈品。 要求是產品可以按先到先到的方式分發給合格的客戶。

例子:

蘋果希望在 3 月份贈送 1000 台 ipad。

他們希望每小時最多贈送 1 個。

他們想把它提供給在加利福尼亞或紐約的客戶。

他們想限制客戶可以獲得的免費 ipad 數量(每 15 天限制 1 個)。

數據結構:

  • 產品- 每個獨特產品 1 個條目。 例如蘋果 iPad

  • 產品贈品

    • 產品編號:AppleIpad
    • 數量:1000
    • 開始日期:03/01/2014
    • 結束日期 03/31/2014
    • 客戶狀態:加利福尼亞州,紐約州
    • 購買限制天數:15

問題:

通過上述結構,我們可以對客戶表進行查詢,並找出哪些符合促銷條件。

我無法弄清楚的是最好的方法是:

  1. 查詢加利福尼亞或紐約的客戶(這是一個連接和另一個表的好用例嗎?)
  2. 當客戶登錄查看哪些免費商品不提供給他時,如果客戶已經獲得此免費贈品,我如何排除 Apple iPad?

換句話說:

  • 假設 amazon.com 想要向我展示我尚未購買的 DVD。 查詢的正確方法是什么?

  • 首先獲取以前購買的產品列表,然后使用 NOT 子句進行查詢是正確的方法嗎?

我假設你會有一張桌子來存放已經贈送的東西。 在此表中,我將包含一個收件人 ID 列,該列可以映射回客戶表。 然后,您可以通過搜索不符合取消資格條件的客戶來創建查詢以查找符合條件的收件人。

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

因為沒有定義明確的數據結構,我將使用以下內容,您可以根據自己設計的任何數據結構進行定制:

  • 產品
    • ProductId - INTEGERIDENTITYPRIMARY KEY
    • 產品名稱 - VARCHAR
  • 狀態
    • StateId - INTEGERIDENTITYPRIMARY KEY
    • 狀態名稱 - VARCHAR
  • 顧客
    • CustomerId - INTEGER ( IDENTITYPRIMARY KEY )
    • StateId - INTEGER (外FOREIGN KEY
  • 晉升
    • PromotionId - INTEGERIDENTITYPRIMARY KEY
    • ProductId - INTEGER (外FOREIGN KEY
    • 數量 - INTEGER
    • 開始日期 - 日期DATETIME
    • 結束日期 - 日期DATETIME
    • PurchaseLimitDays - INTEGER
  • 促銷狀態
    • 促銷INTEGER - 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 子句進行查詢是正確的方法嗎?

可能有更好的方法,子查詢可能會變得非常繁重和緩慢,我建議您嘗試上述一些技術,然后使用分析器來提高效率。

一些數據庫設計

首先,當您將CustomerState設置為California,NewYork您違反了數據庫設計的First Normal Form

因此,讓我們重新組織您的域模型。

狀態- 每個獨特狀態 1 個條目......

客戶- 每個唯一客戶 StateId 1 個條目:(加利福尼亞|紐約|...)...

產品- 每個獨特產品 1 個條目...

ProductGiveAways - 每個產品的多個條目 ProductID Quantity StartDate End Date PurchaseLimitDays ...

ProductGiveAways_State ProductGiveAwaysId STATEID ...

Customer_Product - 每個客戶購買的產品有 1 個條目 CustomerId ProductId PurchaseDate ...

技術問題

當您想查詢加利福尼亞或紐約的客戶時,您現在要做的就是:

// 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

對於 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');
});

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM