2011-05-03 138 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声明来解决此问题。如果我的宝宝没有耳朵感染,我会自己尝试。希望对你有用。