SQL - часы работы - PullRequest
       36

SQL - часы работы

1 голос
/ 03 мая 2011

Мне трудно обернуть голову вокруг того, что кажется довольно простым вопросом. Допустим, у меня есть бизнес, часы которого 12:00 - 3:00 ежедневно. Каждый клиент получает бонус один раз в день в зависимости от его первоначальной покупки в этот день. Итак, допустим, что они потратили двадцать долларов на свою первую транзакцию в тот день - они могли бы получить скидку в двадцать процентов на эту транзакцию, и на этом все.

Я пытаюсь найти наиболее точный способ проверить последний выданный бонус и убедиться, что клиент имеет на него право. Я не могу сделать простой 24-часовой чек, очевидно, потому что, если клиент приходит в 23:00, например, в понедельник и снова в полдень во вторник, он не получит свой второй бонус.

Мы используем внешний интерфейс VB6 для нашей POS с базой данных SQL Server 2008 R2. Каждый раз, когда бонус применяется, он проверяется на стороне базы данных, поэтому я могу легко запросить последний раз, когда бонус был применен.

РЕДАКТИРОВАТЬ: Я должен отметить, что по разным причинам решение не может включать внесение каких-либо изменений в структуру базы данных.

Ответы [ 6 ]

2 голосов
/ 10 мая 2011

Я думаю, что ваш ответ будет чище, если вы измените его на что-то вроде:

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 голосов
/ 03 мая 2011

Я не уверен, с какой стороны (VB или SQL) вы хотите применить логику biz, но в любом случае процесс должен быть одинаковым: вам нужно сохранять ежедневные часы работы каждого клиента с двумя атрибутами:

  • Время (время дня, которое они открывают для бизнеса)
  • TimeSpan (количество часов работы)

Затем вы проверяете, находится ли время транзакции между Time и Time + TimeSpan, чтобы вычислить вашу бизнес-логику и бонус клиента. Оба вычисления довольно просты в VB и SQL. Вам просто нужно убедиться, что вы сохраняете данные логически и используете их последовательно.

0 голосов
/ 04 мая 2011

Я придумала ответ, который меня устраивает, но он немного неуклюжий, и я был бы более чем рад принять более элегантный ответ, если он будет предоставлен. Кроме того, я не проверил это до конца, поскольку уже поздно, но если в моей логике есть недостатки, я с радостью пересмотрю или приму ответ с исправлениями.

По сути, я просто собираюсь определить, что день недели с точки зрения рабочего дня - это день, который начался четыре часа назад. Это означает, что вплоть до 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

Если я добавлю это в хранимую процедуру, я могу просто добавить в нее идентификатор клиента и выдать ему немного, который покажет мне 1, если клиент имеет право, 0 в противном случае. Что мне не нравится в этом, так это то, что, если часы работы клиента заканчиваются намного раньше, я буду потоплен (я думаю, около 7:00 утра, когда простое вычитание четырех часов будет совпадать с предыдущим рабочим днем, но вычитание меньше не будет достаточным для достижения предыдущего рабочего дня). Так что пока это сработает, но я бы хотел увидеть лучшее решение.

0 голосов
/ 03 мая 2011

Чтобы разделить ваши проблемы, я бы добавил новую таблицу, например CUSTOMER_BONUS, со следующими столбцами:

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

Когда вы применяете бонус для клиента на один день, напишитеНовая запись в этой таблице за период, к которому она применяется.Наличие записи в этой таблице указывает на то, что клиент не имеет права на получение другого бонуса от BonusStart до BonusEnd.Когда вы создаете новую продажу, смотрите в этой таблице.Если запись существует, бонуса нет, но если нет, примените бонус и создайте новую запись здесь.

0 голосов
/ 03 мая 2011

Как насчет:

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

Где lastBonusTime - время последней бонусной транзакции?

0 голосов
/ 03 мая 2011

Вы можете посмотреть на проблему немного по-другому. Если клиент здесь (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()

Я бы также рассмотрел специфику данных - вышеприведенное НЕ НАСТРОЕНО ДЛЯ РАБОТЫ В ВСЕХ. Я просто хотел объяснить свой мыслительный процесс.

...