Расчет себестоимости проданного товара

Я пытаюсь рассчитать себестоимость проданных товаров по следующей логике: У меня есть две таблицы: SaleActions и PurchaseActions со следующей структурой:

PurcahseActions: PurchaseId, PurchaseDate, PurchaseLineId, ItemId, Quantity, Price.

SaleActions:SaleId, SaleDate, SaleLineId, ItemId, количество, цена.

Вот пример:

1 августа: 60 ​​единиц товара X приобретаются по курсу 1 доллар США.

2 августа: куплено 5 единиц товара X по курсу 2 доллара США.

5 августа: 63 единицы товара X продаются по цене 1,5 доллара США.

Используя эти данные, я пытаюсь получить следующий набор результатов:

Идентификатор продажи Идентификатор линии продажи Идентификатор покупки PurchaseLineId Количество Цена 3741 24872 21904 23649 60 1 3741 24872 21904 23649 3 2

Это то, что я создал на данный момент:

WITH RankedPurchases AS (SELECT PurchaseId,
                                PurchaseDate,
                                LineId                                                                                AS PurchaseLineId,
                                ItemId,
                                Quantity,
                                Price,
                                SUM(Quantity) OVER (PARTITION BY ItemId ORDER BY PurchaseDate, PurchaseId)            AS CumulativePurchaseQuantity,
                                SUM(Quantity) OVER (PARTITION BY ItemId ORDER BY PurchaseDate, PurchaseId) - Quantity AS PreviousCumulativePurchaseQuantity
                         FROM @PurchaseActions),
     RankedSales AS (SELECT SaleId,
                            SaleDate,
                            LineId                                                                        AS SaleLineId,
                            ItemId,
                            Quantity,
                            SUM(Quantity) OVER (PARTITION BY ItemId ORDER BY SaleDate, SaleId)            AS CumulativeSaleQuantity,
                            SUM(Quantity) OVER (PARTITION BY ItemId ORDER BY SaleDate, SaleId) - Quantity AS PreviousCumulativeSaleQuantity
                     FROM @SaleActions),
     MatchedSales AS (SELECT s.SaleId,
                             s.SaleLineId,
                             p.PurchaseId,
                             p.PurchaseLineId,
                             s.ItemId,
                             s.Quantity                                                                                    AS SaleQuantity,
                             p.Quantity                                                                                    AS PurchaseQuantity,
                             p.Price,
                             s.PreviousCumulativeSaleQuantity,
                             p.PreviousCumulativePurchaseQuantity,
                             ROW_NUMBER() OVER (PARTITION BY s.SaleId, s.SaleLineId ORDER BY p.PurchaseDate, p.PurchaseId) AS RowNum
                      FROM RankedSales s
                               JOIN RankedPurchases p ON s.ItemId = p.ItemId
                      WHERE p.CumulativePurchaseQuantity > s.PreviousCumulativeSaleQuantity
                        AND p.PreviousCumulativePurchaseQuantity < s.CumulativeSaleQuantity)
SELECT SaleId,
       SaleLineId,
       PurchaseId,
       PurchaseLineId,
       CASE
           WHEN RowNum = 1 THEN
               CASE
                   WHEN SaleQuantity <= PurchaseQuantity THEN SaleQuantity
                   ELSE PurchaseQuantity
                   END
           ELSE
               CASE
                   WHEN SaleQuantity - (PreviousCumulativeSaleQuantity - PreviousCumulativePurchaseQuantity) <= PurchaseQuantity
                       THEN SaleQuantity - (PreviousCumulativeSaleQuantity - PreviousCumulativePurchaseQuantity)
                   ELSE PurchaseQuantity
                   END
           END AS Quantity,
       Price
FROM MatchedSales
ORDER BY ItemId, SaleId, SaleLineId, RowNum

Однако мой результат показывает количество как 60 и 5 вместо 60 и 3. Полный запрос с минимально воспроизводимыми данными: https://sqlfiddle.com/sql-server/online-compiler?id=0332881c-690e-4ca9-9e22-5cb255bf74c9.

Вопросы должны быть самостоятельными, т.е. Содержимое вашей скрипки должно быть включено в ваш вопрос.

Dale K 15.08.2024 20:41

А как рассчитывается себестоимость товара, ФИФО, ЛИФО, взвешивается? SO - это не бесплатный веб-сайт службы кодирования, вам нужно продемонстрировать некоторые усилия, а не просто написать несколько слов и посмотреть, как люди это делают.

siggemannen 15.08.2024 20:51

привет @DaleK, спасибо за отзыв и редактирование. Я полностью отредактировал запрос.

Kanan Mammadov 16.08.2024 16:20

@siggemannen спасибо за отзыв. Я обновил описание со всеми необходимыми деталями.

Kanan Mammadov 16.08.2024 16:20
ReactJs | Supabase | Добавление данных в базу данных
ReactJs | Supabase | Добавление данных в базу данных
Это и есть ваш редактор таблиц в supabase.👇
Понимание Python и переход к SQL
Понимание Python и переход к SQL
Перед нами лабораторная работа по BloodOath:
2
4
56
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Это довольно распространенный запрос перекрывающихся диапазонов. Хотя ваша проверка условия перекрытия верна (End1 > Start2 && Start1 < End2), расчет длины (количества) перекрытия неверен.

Вы можете рассчитать правильную величину перекрытия, используя LEAST(End1, End2) - GREATEST(Start1, Start2). Для вашего запроса это будет:

LEAST(CumulativePurchaseQuantity, CumulativeSaleQuantity)
    - GREATEST(PreviousCumulativePurchaseQuantity, PreviousCumulativeSaleQuantity)
    AS Quantity

Функции LEAST() и GREATEST() являются новыми в SQL Server 2022. Для более ранних версий вы можете вычислить эквивалент с помощью выражения CASE или функции IIF():

IIF(CumulativePurchaseQuantity < CumulativeSaleQuantity,
    CumulativePurchaseQuantity, CumulativeSaleQuantity)
    - IIF(PreviousCumulativePurchaseQuantity > PreviousCumulativeSaleQuantity,
          PreviousCumulativePurchaseQuantity, PreviousCumulativeSaleQuantity)
    AS Quantity

Вышеупомянутое требует, чтобы вы предоставили значения PreviousCumulativeSaleQuantity и CumulativePurchaseQuantity в результатах MatchedSales CTE или поочередно переместили этот расчет количества внутрь этого CTE. Вы можете обнаружить, что CTE больше не нужен, если объедините его содержимое с окончательным выбором.

Примеры результатов (с некоторыми дополнительными данными испытаний и разными столбцами):

Идентификатор продажи ПродажаКоличество Идентификатор покупки ПокупкаКоличество ПримененноеКоличество От# К# 1 63 1 60 60 0 60 1 63 2 5 3 60 63 2 15 2 5 2 63 65 2 15 3 10 10 65 75 2 15 4 20 3 75 78

См. эту db<>fiddle для демонстрации.

Другие вопросы по теме