Datetime SQL-运行小时数

Datetime SQL-运行小时数,datetime,vb6,sql-server-2008-r2,Datetime,Vb6,Sql Server 2008 R2,我很难把这个看似简单的问题放在心上。假设我有一家公司,每天的营业时间是中午12点到凌晨3点。根据当天的首次购买情况,每位客户每天可获得一次奖金。所以,假设他们那天第一笔交易花了20美元——他们可能会在那笔交易上得到20%的折扣,这就是当天的情况 我试图找出最准确的方法来检查上次发放的奖金,并确保客户有资格获得奖金。很明显,我不能做一个简单的24小时检查,因为如果客户在周一晚上11点进来,然后在周二中午再次进来,他们将无法获得第二笔奖金 我们的POS机使用VB6前端,带有SQL Server 20

我很难把这个看似简单的问题放在心上。假设我有一家公司,每天的营业时间是中午12点到凌晨3点。根据当天的首次购买情况,每位客户每天可获得一次奖金。所以,假设他们那天第一笔交易花了20美元——他们可能会在那笔交易上得到20%的折扣,这就是当天的情况

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

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


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

您可以稍微不同地看待这个问题。如果客户现在在这里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()

<>我也会考虑数据的细节,上面根本没有调整性能。我只是想解释一下我的思维过程。

你可以用不同的方式看待这个问题。如果客户现在在这里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()

<>我也会考虑数据的细节,上面根本没有调整性能。我只是想解释一下我的思维过程。

我不确定你想在VB或SQL哪一方应用商业逻辑,但在任何一种情况下,过程都应该是相同的:你需要用两个属性来保持每个客户每天的运营时间:

他们每天营业的时间 时间跨度运行小时数
然后检查事务的时间是否介于time和time+TimeSpan之间,以计算业务逻辑和客户奖金。在VB和SQL中,这两种计算都相当简单。您只需要确保逻辑上持久化数据并一致地使用它。

我不确定您希望在VB或SQL哪一方应用业务逻辑,但在任何一种情况下,流程都应该是相同的:您需要使用两个属性持久化每个客户的日常操作时间:

他们每天营业的时间 时间跨度运行小时数 然后检查事务的时间是否介于time和time+TimeSpan之间,以计算业务逻辑和客户奖金。在VB和SQL中,这两种计算都相当简单。您只需确保以逻辑方式保存数据并一致使用它。

如何:

IF (DATEPART(dayofyear, [lastBonusTime]) <> DATEPART(dayofyear, GetDate())) ...
LastBonuTime是上次奖金交易的时间吗?

如何:

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

其中lastBonusTime是上次奖金交易的时间?

为了区分您的顾虑,我将添加一个新表,如CUSTOMER\u bonus,其中包含以下列:

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

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

为了分离您的顾虑,我将添加一个新表,如CUSTOMER_bonus,其中包含以下列:

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

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

我提出了一个我满意的答案,但有点含糊不清,如果提供了一个更优雅的答案,我将非常乐意接受。此外,我还没有完全测试过这个,因为时间已经很晚了,但是如果我的逻辑有缺陷,我会很乐意修改或者接受修改后的答案

基本上,我只想确定一周中的一天,就一个工作日而言,是四小时前开始的任何一天。这意味着一直到凌晨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点左右沉没,那时简单地减去四个小时将与前一个工作日重叠,但减去更少的时间将不足以到达前一个工作日。因此,这将暂时奏效,但我希望看到更好的解决方案。

我提出了一个我满意的答案,但有点含糊不清,如果有更优雅的答案,我将非常乐意接受。此外,我还没有完全测试过这个,因为时间已经很晚了,但是如果我的逻辑有缺陷,我会很乐意修改或者接受修改后的答案

基本上,我只想确定一周中的一天,就一个工作日而言,是四小时前开始的任何一天。这意味着一直到凌晨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点左右沉没,那时简单地减去四个小时将与前一个工作日重叠,但减去更少的时间将不足以到达前一个工作日。因此,它暂时有效,但我希望看到更好的解决方案。

如果您将其修改为以下内容,我认为您的答案会更清晰:

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

然后按照建议添加timespan以获得关闭时间。这可能有点棘手,因为如果是在午夜之后,则需要将开放时间添加到之前的日期,但您可能可以通过案例陈述来解决这个问题。如果我的孩子没有耳朵感染的话,我会自己试试。希望这对您有用。

如果您将其修改为以下内容,我认为您的答案会更清晰:

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

然后按照建议添加timespan以获得关闭时间。这可能有点棘手,因为如果是在午夜之后,则需要将开放时间添加到之前的日期,但您可能可以通过案例陈述来解决这个问题。如果我的孩子没有耳朵感染的话,我会自己试试。希望这对您有用。

这样,如果客户昨天晚上11点和今天晚上9点买了一件商品,您将拒绝给他折扣。这样,如果客户昨天晚上11点和今天晚上9点买了一件商品,您将拒绝给他折扣。我应该说明,出于各种原因,我们无法制定一个涉及修改数据库的解决方案。我喜欢的方法是进一步规范化数据库,并在这个过程中建立类似的东西,但不幸的是,这不是我们现在可以做的。我应该说,出于各种原因,我们无法建立一个涉及修改数据库的解决方案。我最喜欢的方法是进一步规范数据库,并在该过程中建立类似的机制,但不幸的是,这不是我们现在可以做的。如果客户在周一的工作日晚上11点进行首次购买,然后,当他们在周二上午12点(周一仍然是营业日)再次购买时,他们将获得额外奖金。我的问题是计算营业时间,因此周二上午12点至凌晨3点基本上仍被视为周一。对不起,您的问题中错误理解了营业日规则。如果客户在周一的营业日星期一晚上11点进行首次购买,然后,当他们在周二上午12点(周一仍然是营业日)再次购买时,他们将获得额外奖金。我的问题是计算营业时间,因此周二上午12点至凌晨3点基本上仍被视为周一。对不起,从您的问题中误解了营业日规则