В моей базе данных 2 таблицы 1. ИНВЕНТАРЬ с атрибутами ID, Name, QOH (т. Е. Количество в наличии)

  1. INVENTORY_ADJUSTMENT с атрибутами Date, AdjQty, QOH, Notes

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

Пока это работало нормально. Но теперь у некоторых клиентов есть требование вернуться на месяц назад и обновить имеющееся количество. Так, например: 10 апреля пользователь может вернуться и изменить QOH 1 марта. Если бы это было разрешено, то каждую запись, которую я сделал в таблице INVENTORY_ADJUSTMENT с 1 марта по 10 апреля, также необходимо было бы обновить, поскольку каждая строка INVENTORY_ADJUSTMENT имеет поле QOH, которое теперь будет не синхронизировано.

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

2
user1763470 18 Апр 2015 в 03:07

1 ответ

Лучший ответ

Проблема

Сначала вам нужно понять, что это за проблема и что вы ее создали. После этого у нас будет другой контекст, и мы сможем обсудить возможные решения.

  1. Inventory - это надежная, постоянная таблица фактов. Идея состоит в том, что в любой момент времени, если здание задымляется, таблица окончательно определяет положение запасов компании.

  2. Таблица InventoryAdjustment - это просто транзакция с запасами компании, с таблицей Inventory. Его можно было назвать Transaction.

  3. Столбец InventoryAdjustment.QoH - это дублированный столбец. QoH уже существует в Inventory. Когда вы создаете дублированный столбец, у вас есть:

    • нарушены правила нормализации (и, таким образом, у вас есть хорошо известная классическая ошибка, которую нам рекомендуется избегать и которая имеет последствия). Ваши таблицы больше не нормализованы, ваша база данных не является базой данных.

    • представил аномалию обновления. Это означает, что вам необходимо обновить данные (значение, которое является единственной версией истины) более чем в одном месте, в противном случае два (или более) элемента «рассинхронизируются». Идея в том, чтобы вообще не создавать дубликаты.

    • Если вы внедрили это для получения промежуточной суммы (InventoryAjustment.QoH, в последовательных строках), вы обманываете себя. Промежуточная сумма (Inventory.QoH плюс все корректировки до текущей строки) легко вводится в коде SQL. Попросите, если вам это нужно.

Теперь вы уже привыкли к такому ошибочному положению вещей, вы не рассматриваете его как ошибку, до сих пор оно «работало нормально». Поэтому вам может быть трудно признать, что это ошибка. Я оставлю это на ваше усмотрение.

  • Ключевой термин - «до сих пор». Классически такие ошибки становятся проблемой только тогда, когда обнаруживается ошибка или когда пользователь хочет что-то изменить. Итак, во-первых, их нужно разоблачить и понять, что они из себя представляют.

  • Событие только что произошло, вышеперечисленное сработало.

Решение

  • Отбросьте столбец InventoryAdjustment.QoH.

  • Сохраняйте повторный расчет и обновление столбца Inventory.QoH всякий раз, когда вставляется строка InventoryAdjustment.

  • Теперь столбец Inventory.QoH является истинным , и это всегда верно. Он отражает точное QoH на складе прямо сейчас.

  • Никакой "синхронизации" не требуется, потому что в файле нет двух версий правды или двух копий одной правды.

Конец истории.

Требование нового пользователя

Теперь у некоторых клиентов есть требование вернуться на месяц назад и обновить имеющееся количество. Как поддержать возможность ввода количества запасов с задним числом дат?

  • Теперь исправленная база данных прекрасно справляется с этим.

    • Обратите внимание, поскольку база данных была исправлена, есть только одно значение QoH. Если бы его не исправили, пришлось бы остановиться и спросить:

      <цитата>

      Какое значение QoH они хотят обновить: промежуточный, реальный или и то, и другое?
      Какой цели он служит?

  • Приложение требует небольшой настройки. Я предполагаю, что текущая функция устанавливает InventoryAdjustment.Date на текущую дату перед вставкой.

    • Добавьте функцию, позволяющую привилегированному пользователю (например, которому было предоставлено разрешение "супервизор", чтобы разрешить это) set InventoryAdjustment.Date до действительной даты в прошлом, ограничивая ее на (например) 30 дней или что-то еще.
  • Когда транзакция выполняется, она изменяет Inventory.QoH обычным способом.

Конец истории.

(Если это не так, это будет означать, что есть важные детали, которые не были сообщены. Пожалуйста, сделайте это.)

Пластырь Fix

Если вы не понимаете (а) характер ошибки и (б) правдивость исправления, т.е. вы счастливы сохранить его, тогда ...

Если бы это было разрешено, то каждую запись, которую я сделал в таблице INVENTORY_ADJUSTMENT в период с 1 марта по 10 апреля, также необходимо было бы обновить, поскольку каждая строка INVENTORY_ADJUSTMENT имеет поле QOH, которое теперь будет не синхронизировано. .

Да.

Это следствие аномалии обновления. Все повторяющиеся значения InventoryAdjustment.QoH для скорректированного элемента теперь в любом случае считаются ложными. Записывать их не было и не имеет смысла. Но вы их записали. И теперь их нужно обновить.

Код это.

4
PerformanceDBA 18 Апр 2015 в 13:40
1
Давайте сделаем это правильно, как вы сказали, с одним QOH в таблице инвентаризации - Current QOH. Итак, скажем, 1 апреля 2015 года я хочу получить QOH всех элементов инвентаризации 1 апреля 2014 года. Для каждого элемента инвентаря мне нужно выполнить QOH сегодня - суммировать все транзакции между сегодняшним днем ​​и 12 месяцами? Разве это не будет ужасно дорого?
 – 
user1763470
18 Апр 2015 в 14:55
2
Вовсе нет, это нормальный (правильный) метод, его используют миллионы сайтов, эта структура широко используется в бухгалтерских и банковских системах, где есть дополнительная сложность требований аудита. (1) если ваши таблицы разумны (без отрицательной производительности), а количество строк на элемент составляет несколько тысяч, скорость будет прямой: зависит от количества извлеченных строк. (2) Если бы у вас были реляционные ключи, это было бы невероятно быстро, потому что каждый элемент обращался бы к очень маленькой ветви B-дерева.
 – 
PerformanceDBA
19 Апр 2015 в 02:57
(3) если и только если у компании есть идея проведения аудита физической инвентаризации и записи постоянного QoH для каждой единицы (скажем, ежегодно), что является «показателем качества аудита» и не изменяется после этой даты, тогда существует является усовершенствованием (добавлением, а не изменением), чтобы справиться с этим. Пользователь должен вдумчиво выбрать дату окончания (ежеквартально, ежегодно).
 – 
PerformanceDBA
19 Апр 2015 в 03:04
2
Вы находитесь в другой лиге, мой друг. Большое спасибо за ясное объяснение и отличные ответы.
 – 
user1763470
19 Апр 2015 в 05:27
2
Спасибо. С удовольствием. (4) Если вам интересно, я обновил этот ответ, чтобы разобраться с комментариями там.
 – 
PerformanceDBA
20 Апр 2015 в 11:39