сложные подзапросы в MySQL с использованием FIFO Dynamic CTE

У меня есть 3 таблицы как:

Первая таблица: (покупка)

date (mm-dd)    quantity   p_id
    05-05          3         1
    05-06          2         1

Вторая таблица: (Продажи)

date (mm-dd)    quantity   p_id
    05-07          1         1

Третья таблица: (срок действия истек)

date (mm-dd)    quantity   p_id
    05-08          4         1

Теперь я хочу получить подробную информацию о продуктах, срок действия которых истек:

  • При покупке продукта с истекшим сроком годности (FIFO)
  • Продукт, который был куплен первым, истечет/продастся первым.

Результат должен быть:

purchase_date      expired_date      quantity    p_id
  05-05               05-08             2         1
  05-06               05-08             2         1

Объяснение,

  • Всего в магазине 5 товаров от 05-06 с p_id: 1,
  • затем 05-07 1 было продано количество p_id: 1 т.е. товар, полученный 05-05, был продан первым согласно FIFO

так что теперь продукт у нас есть: (только для визуализации)

date (mm-dd)    quantity   p_id
    05-05          2         1   -its 1 quantity is sold
    05-06          2         1

Затем срок действия истекает 05-08, продукты с истекшим сроком годности: (по FIFO)

purchase_date      expired_date      quantity   p_id
  05-05               05-08             2         1
  05-06               05-08             2         1

т. е. 2 продуктов из 05-05 истекли, а 2 из 05-06

На данный момент я реализую следующую логику:

Все добавленные транзакции:

date (mm-dd)    quantity   p_id    expired
    05-05          3         1      False
    05-06          2         1      False
    05-07         -1         1      False
    05-08         -4         1      True

Добавить все транзакции как: (как показано выше)
Установить количество sell и expiry как отрицательное, а expired переменную, True только в случае истечения срока действия транзакции

Алгоритм: (используя концепцию deque push pop, по истечении срока действия записывать в журнал)

  1. для каждой группы p_id транзакций:
  2. инициализировать deque (пусто)
  3. за каждую транзакцию (все присоединенные транзакции)
  4. если количество положительное, вставить дек
  5. иначе поп,
  6. если нет всплывающего окна, пропустите (так как продажа может быть больше, чем покупка)
  7. иначе если expired является ложным, т.е. является транзакцией продажи,
  8. pop до тех пор, пока разница продаж и популярности не станет больше нуля
  9. в противном случае это ненужная запись
  10. всплывать до тех пор, пока разница не станет больше нуля, а также регистрировать каждое всплывающее окно с разницей

* Я останавливаюсь, когда разница больше или равна нулю, что означает, что было куплено больше количества, чем продано, поскольку количество проданных товаров отрицательное, рассмотрим:

bought = 2
sold = -4
diff = 2-4 = -2
therefore we need to loop for next purchase until diff >= 0

На самом деле в настоящее время, как я все это делаю, загружаю все эти данные из моего RDBMS в pandas dataframe, а затем применяю некоторые вещи, очевидно, это не поддерживается, я хочу сделать это в самой базе данных, поскольку база данных оптимизирована, я хочу сделать сложный MySQL query, который делает sub-queries для получения желаемого результата.

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

В основном происходит следующее:

  • Магазин покупает товар, делается запись о покупке,
  • Магазин продает товар, делается запись о продаже,
  • Магазин сообщает, что этот продукт просрочен, делается запись об истечении срока годности.

*Между ними нет отношений.

Также я использую Django Querysets для получения данных, поэтому, если бы я мог использовать это, это было бы здорово!

Также я открыт для внесения изменений или использования совершенно другого инструмента для их достижения.


person Aashish Gahlawat    schedule 14.09.2018    source источник
comment
Вы собираетесь использовать или планируете использовать MySQL-8.0+ или MariaDB -10.2+, которые поддерживают рекурсивные CTE? Там может быть путь. В дополнение к этим таблицам корректировки вам может понадобиться таблица stock_take с абсолютными числами, или каждый запрос должен будет полностью сканировать все 3 таблицы, но, возможно, это не проблема.   -  person danblack    schedule 14.09.2018
comment
Возможен ли слэйв репликации для анализа (возможен слэйв 8.0 от мастера 5.7)? рекурсивный пример MSSQL, который может намекнуть. Заинтересованы в создании db-fiddle с демонстрационными данными в MySQL-8.0 для совместного использования?   -  person danblack    schedule 14.09.2018
comment
У меня есть innodb 5.7.21, на самом деле мне нужны эти данные для какой-то цели, и все, что я могу сделать, это изменить/создать какую-то таблицу, но мне не разрешено изменять версию базы данных.   -  person Aashish Gahlawat    schedule 14.09.2018
comment
Извините, сэр, так как я не очень хорошо знаком с большинством терминов базы данных, только запустил, не смог получить вас всех, но, возможно, ссылка на пример поможет.   -  person Aashish Gahlawat    schedule 14.09.2018
comment
@danblack данные хранятся в FIFO, как я могу поддерживать это, сэр?   -  person Aashish Gahlawat    schedule 14.09.2018
comment
подчиненное устройство репликации будет вторым экземпляром сервера mysql, который получает обновляется в зависимости от того, какие изменения происходят в экземпляре 5.7.21. Поскольку вы выполняете доступ только для чтения на ведомом устройстве 8.0 для выполнения CTE, это может произойти без каких-либо изменений на ведущем экземпляре 5.7.21. FIFO поддерживается как временная таблица, такая как таблица результатов описано в обзоре MariaDB.   -  person danblack    schedule 14.09.2018
comment
FWIW, я начал смотреть, как это сделать с помощью CTE. Глядя на покупки и просроченные, они стали выглядеть так, как данные, которые я поместил в этот отчет об ошибке. Таким образом, MariaDB может одновременно обрабатывать только один просроченный продукт, а MySQL-8.0 не может обрабатывать ORDER BY/LIMIT в рекурсивном CTE.   -  person danblack    schedule 15.09.2018
comment
Приведенный выше отчет об ошибке mariadb был исправлен и будет включен в следующие версии 10.2/10.3. Рекурсивный CTE в отчете об ошибке работает путем обратного отсчета (в идентификаторе покупки) просроченных объемов по мере того, как он работает в обратном направлении через покупки. Еще немного работы требуется, чтобы учесть продажи и другие элементы с истекшим сроком действия.   -  person danblack    schedule 19.09.2018
comment
@danblack, так что, сэр, в mysql пока нет обходного пути! Должен ли я придерживаться своей старой реализации deque?   -  person Aashish Gahlawat    schedule 19.09.2018