SQL - 操作时间

时间:2011-05-03 15:16:14

标签: datetime vb6 sql-server-2008-r2

我很难绕过看似简单的问题。假设我的营业时间是每天中午12点至凌晨3点。每位客户每天根据他们当天的首次购买获得奖金。所以,假设他们当天在第一笔交易上花了二十美元 - 他们可能会在这笔交易上获得20%的折扣,这就是当天。

我正在试图找出最准确的方法来检查最后给出的奖金,并确保客户有资格获得奖金。显然,我不能做一个简单的24小时检查,因为如果客户在星期一晚上11点进来,并且在周二中午再次进来,他们将无法获得他们的第二次奖金。

我们正在使用带有SQL Server 2008 R2数据库的POS的VB6前端。每次应用奖金时,都会在数据库方面进行审核,因此我可以轻松查询上次应用奖金的时间。

编辑:我应该注意,由于各种原因,解决方案不能包括对数据库结构进行任何更改。

6 个答案:

答案 0 :(得分:2)

我不确定您要在哪一方(VB或SQL)应用商业逻辑,但在任何一种情况下,流程都应该相同:您需要使用两个属性来保持每个客户的每日营业时间:

  • 时间(他们营业的时间)
  • TimeSpan(营业时数)

然后检查交易的时间是否在TimeTime + TimeSpan之间,以计算您的业务逻辑和客户的奖金。在VB和SQL中,这两种计算都相当简单。您只需确保以逻辑方式保留数据并始终如一地使用它。

答案 1 :(得分: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语句来解决这个问题。如果我的宝宝没有感染耳朵,我会亲自尝试一下。希望对你有用。

答案 2 :(得分: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 c.CustomerId=@CustomerId
       AND LastVisitDt BETWEEN 
           ( 
              DATEADD(hh,12,convert(DATE, LastVisitDt))
           )
           AND
           ( 
              DATEADD(hh,27,convert(DATE, LastVisitDt))
           )               
       AND DATEADD(hh,24,LastVisitDT)<=GETDATE()

我还会考虑数据的具体细节 - 上面的内容根本没有表现出来。我只是想解释一下我的思考过程。

答案 3 :(得分:0)

怎么样:

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

lastBonusTime是最后一笔奖金交易的时间?

答案 4 :(得分:0)

为了分离您的疑虑,我会在这些列中添加一个新表格,例如CUSTOMER_BONUS

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

当您为某一天的客户申请奖金时,请在此表中为其适用的期间写下新记录。此表中记录的存在表明该客户没有资格获得BonusStartBonusEnd之间的其他奖励。创建新销售时,请查看此表。如果记录存在,则没有奖金,但如果没有,则应用奖金并在此处创建新记录。

答案 5 :(得分: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点,当简单地减去四个小时将重叠到前一个工作日时,但减去更少不足以达到前一个工作日)。所以它暂时会起作用,但我很乐意看到更好的解决方案。