2011-05-03 137 views
1

我很難過,看起來是一個很簡單的問題。假設我有一個企業,其工作時間是每天12點到凌晨3點。根據當天的初次購買,每位客戶每天獲得一次獎金。所以,假設他們當天的第一筆交易花費了二十美元 - 他們可能會在該交易中獲得百分之二十的折扣,那就是那一天。SQL - 運行時間

我想弄清楚最準確的方法來檢查最後的獎金,並確保客戶有資格獲得一個。顯然,我不能做一個簡單的24小時支票,因爲如果客戶在星期一晚上11點進來,並且在週二中午再次進入,他們將不會獲得他們的第二個獎金。

我們正在爲我們的POS使用VB6前端,並使用SQL Server 2008 R2數據庫。每次應用獎金時,都會在數據庫方面進行審計,以便我可以輕鬆查詢最後一次應用獎金的時間。

編輯:我應該注意到,由於各種原因,解決方案不能包括對數據庫的結構進行任何更改。

回答

0

我想出了一個我很滿意的答案,但這有點不合適,如果提供了一個更優雅的答案,我會非常樂意接受更優雅的答案。另外,我還沒有徹底地測試過,因爲它在一天晚了,但如果我的邏輯有缺陷,我會很樂意修改或接受修改的答案。

基本上,我只是要確定一個工作日的星期幾是四小時前開始的那一天。這意味着,一直到凌晨3:59,「今天」將在前一天被考慮,這對於這些小時的操作是正確的(我超過了上午3點的關閉時間,以說明一個站點決定保持打開狀態一會兒)。然後,我使用相同的規則將這段時間與最近一次獎金應用於該客戶的帳戶的時間進行比較。如果兩者匹配,獎金將在這個營業日應用。如果它們不同,則它不具有,並且客戶有資格。

DECLARE @CustID AS int 
DECLARE @LastBonus AS date 
DECLARE @BonusDue AS bit 

SET @LastBonus = (SELECT TOP 1 [DateTime] FROM Audit WHERE CustomerID = @CustID AND TransactionType = 'BONUS' ORDER BY [DateTime] DESC) 

IF (SELECT DATEADD(hh, -4, CURRENT_TIMESTAMP)) <> 
    (SELECT DATEADD(hh, -4, @LastBonus)) 
    BEGIN 
     SET @BonusDue = 1 
    END 
ELSE 
    BEGIN 
     SET @BonusDue = 0 
    END 

如果我把這個存儲過程,我可以簡單地扔在一個客戶ID,並把它吐了一下那會告訴我1如果客戶符合條件,否則爲0。我不喜歡它的是,如果客戶的營業時間早得多,我就會陷入沉寂(我估計在上午7點左右,僅僅減去四個小時就會重疊到前一個營業日,但減去不足以達到前一個營業日)。所以它暫時會奏效,但我很想看到更好的解決方案。

0

你可以看看問題有點不同。如果客戶現在在這裏(GETDATE()),那麼他們上次購買後已超過24小時?

所以,像

SELECT * 
FROM Customers c 
    INNER JOIN CustomerVisits cv 
    ON c.CustomerId=cv.CustomerId 
    INNER JOIN CustomerBonus cb 
    ON cv.VisitId=cb.VisitId 
    WHERE [email protected] 
     AND LastVisitDt BETWEEN 
      ( 
       DATEADD(hh,12,convert(DATE, LastVisitDt)) 
      ) 
      AND 
      ( 
       DATEADD(hh,27,convert(DATE, LastVisitDt)) 
      )    
     AND DATEADD(hh,24,LastVisitDT)<=GETDATE() 

我還要考慮數據的細節 - 上面是NOT性能調整的。我只是想解釋我的思維過程。

+1

這樣,如果您昨天晚上11點和今天晚上9點買了一件物品,您將拒絕客戶的折扣。 – blubb 2011-05-03 15:26:53

+0

@Simon Stelling,請看最新的編輯版本 – dawebber 2011-05-03 15:40:23

2

我不確定你想應用biz邏輯的哪一方(VB或SQL),但在任何一種情況下,過程應該是相同的:你需要堅持每個客戶的每日工作時間與兩個屬性:

  • 時間(他們開門營業一天的時間)
  • 時間跨度(工作小時數)

你再檢查是否有交易的時間是TimeTime + TimeSpan之間計算業務邏輯和客戶的獎金。這兩種計算在VB和SQL中都相當簡單。您只需確保從邏輯上堅持數據並持續使用它。

+0

謝謝。我認爲這讓我的大腦在正確的地方。 – 2011-05-03 20:48:47

0

如何:

IF (DATEPART(dayofyear, [lastBonusTime]) <> DATEPART(dayofyear, GetDate())) ... 

哪裏lastBonusTime是最後的獎金事務的時間?

+0

因此,如果客戶要在星期一晚上11點的營業日進行首次購買,那麼當他們在週二的12點(這應該仍然是週一的營業日)再次購買時,他們將獲得額外的獎金。我的問題是佔用運行時間,因此基本上星期二的凌晨12點到凌晨3點仍被視爲星期一。 – 2011-05-03 19:35:22

+0

對不起,誤解了您的問題 – Christo 2011-05-03 20:29:59

0

在分離您的問題的興趣,我想補充一個新的表,像CUSTOMER_BONUS,這些列:

BonusStart datetime 
BonusEnd datetime 
CustomerID int/uniqueidentifier/whatever 
TransactionID int/whatever (points to what qualified for the bonus) 

當您申請的獎金一天一個客戶,寫一個新記錄此表適用於此期間。此表中記錄的存在表示客戶不符合BonusStartBonusEnd之間的其他獎勵。當您創建新的銷售時,請查看此表。如果記錄存在,沒有獎金,但如果沒有,則應用獎金並在此處創建新記錄。

+0

中的工作日規則我應該說明,由於各種原因,我們無法建立涉及更改數據庫的解決方案。我最喜歡的方法是將數據庫進一步正常化,並將這樣的事情作爲這一過程的一部分,但不幸的是,我們現在不能這樣做。 – 2011-05-03 16:50:34

2

,我認爲你的答案是清潔,如果你修改了它喜歡的東西:

IF @LastBonus BETWEEN @store_open AND @store_close 
    BEGIN 
    SET @BonusDue = 0 
    END 
ELSE 
    BEGIN 
    SET @BonusDue = 1 
    END 

,你的身影基於被添加到最後的日期部分固定時間店裏打開和關閉日期獎金。類似於

Set @openTime = '12:00' 
Convert(date, @LastBonus) + @openTime 

然後添加時間跨度(如建議)以獲得關閉時間。這可能有點棘手,因爲如果在午夜之後,開放時間將需要添加到上一個日期,但您可以使用CASE聲明來解決此問題。如果我的寶寶沒有耳朵感染,我會自己嘗試。希望對你有用。