Итоговая сумма TSQL - PullRequest
       1

Итоговая сумма TSQL

2 голосов
/ 28 апреля 2011

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

Элементы:

ItemNumber     QuantityOnHand
----------     --------------
B34233         25.0
B34234         10.0

ItemTransactions:

TransDate      ItemNumber     Quantity
-----------    ----------     --------
1/1/2011       B34233         10.0
1/2/2011       B34234         -15.0
1/2/2011       B34233         -5.0
1/4/2011       B34234         -10.0

Вот результат, который я хочу получить из запроса:

Date          ItemNumber      Quantity
----          ----------      --------
12/31/2010    B34233          20.0
12/31/2010    B34234          35.0
1/1/2011      B34233          30.0
1/1/2011      B34234          35.0
1/2/2011      B34233          25.0
1/2/2011      B34234          20.0
1/3/2011      B34233          25.0
1/3/2011      B34234          20.0
1/4/2011      B34233          25.0
1/4/2011      B34234          10.0

Как мне написать этот запрос?Я достаточно хорошо знаю TSQL, но не могу найти способ написать этот запрос.

Ответы [ 3 ]

1 голос
/ 28 апреля 2011

В SQL Server 2005 и выше:

WITH    dates (itemNumber, quantity, currentDate, minDate) AS
        (
        SELECT  itemNumber, CAST(quantityOnHand AS DECIMAL(20, 2)), it.*
        FROM    items i
        CROSS APPLY
                (
                SELECT  MAX(transDate) AS currentDate,
                        MIN(transDate) AS minDate
                FROM    itemTransactions it
                ) it
        UNION ALL
        SELECT  d.itemNumber,
                CAST
                (
                d.quantity -
                COALESCE(
                (
                SELECT  it.quantity
                FROM    itemTransactions it
                WHERE   it.transDate = d.currentDate
                        AND it.itemNumber = d.itemNumber
                ), 0) AS DECIMAL(20, 2)),
                DATEADD(d, -1, currentDate),
                minDate
        FROM    dates d
        WHERE   currentDate >= minDate
        )
SELECT  currentDate, itemNumber, quantity
FROM    dates
ORDER BY
        currentDate, itemNumber

Это предполагает, что у вас есть одна транзакция на элемент в день (это рекурсивное ограничение CTE в SQL Server).

Если вы этого не сделаете, вы должны добавить еще один CTE, который будет агрегировать транзакции по дням и пунктам, и использовать его вместо items:

WITH    itGrouped (transDate, itemNumber, quantity) AS
        (
        SELECT  transDate, itemNumber, SUM(quantity)
        FROM    itemTransactions
        GROUP BY
                transDate, itemNumber
        ),
        dates (itemNumber, quantity, currentDate, minDate) AS
        (
        SELECT  itemNumber, CAST(quantityOnHand AS DECIMAL(20, 2)), it.*
        FROM    items i
        CROSS APPLY
                (
                SELECT  MAX(transDate) AS currentDate,
                        MIN(transDate) AS minDate
                FROM    itGrouped it
                ) it
        UNION ALL
        SELECT  d.itemNumber,
                CAST
                (
                d.quantity -
                COALESCE(
                (
                SELECT  it.quantity
                FROM    itGrouped it
                WHERE   it.transDate = d.currentDate
                        AND it.itemNumber = d.itemNumber
                ), 0) AS DECIMAL(20, 2)),
                DATEADD(d, -1, currentDate),
                minDate
        FROM    dates d
        WHERE   currentDate >= minDate
        )
SELECT  currentDate, itemNumber, quantity
FROM    dates
ORDER BY
        currentDate, itemNumber
0 голосов
/ 28 апреля 2011

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

Хорошее / быстрое решение, если у вас нет транзакций по 100 КБ и / или приличный sql box.

Извините за грязный SQL (код обеденного времени: P)

CREATE TABLE #transactions (ID INT, DTE DATETIME, PROD VARCHAR(25), QTY INT )
CREATE TABLE #products (ID VARCHAR(25))
CREATE TABLE #dates (DTE DATETIME)

-- create some dates - you would do this dynamically
INSERT INTO #dates values (convert(datetime, '01/01/2011', 103))
INSERT INTO #dates values (convert(datetime, '02/01/2011', 103))
INSERT INTO #dates values (convert(datetime, '03/01/2011', 103))

-- create some products - you would get these from where-ever they live
INSERT INTO #products values ('A')
INSERT INTO #products values ('B')

-- create some transactions - you would get these from where-ever they live
INSERT INTO #transactions values (1, convert(datetime, '01/01/2011', 103), 'A', 25)
INSERT INTO #transactions values (2, convert(datetime, '01/01/2011', 103), 'A', -5)
INSERT INTO #transactions values (3, convert(datetime, '02/01/2011', 103), 'A', 60)
INSERT INTO #transactions values (4, convert(datetime, '02/01/2011', 103), 'A', -15)
INSERT INTO #transactions values (5, convert(datetime, '03/01/2011', 103), 'A', 100)
INSERT INTO #transactions values (6, convert(datetime, '03/01/2011', 103), 'A', -20)

INSERT INTO #transactions values (7, convert(datetime, '01/01/2011', 103), 'B', 10)
INSERT INTO #transactions values (8, convert(datetime, '01/01/2011', 103), 'B', 5)
INSERT INTO #transactions values (9, convert(datetime, '02/01/2011', 103), 'B', -30)
INSERT INTO #transactions values (1, convert(datetime, '02/01/2011', 103), 'B', 50)
INSERT INTO #transactions values (11, convert(datetime, '03/01/2011', 103), 'B', 10)
INSERT INTO #transactions values (12, convert(datetime, '03/01/2011', 103), 'B', 200)

-- Join dates and transactions - Do a sub select from 'begining of time' to get qty on hand per day
SELECT CONVERT(VARCHAR(25), a.DTE, 103),  b.id, (SELECT sum(qty) from #transactions c where b.id = c.prod and c.DTE <= a.DTE)
FROM #dates a, #products b

-- One benefit to this approach means you can genereate qty_on_hand per days were no transactions have occured (if you needed this)

DROP TABLE #transactions
DROP TABLE #products
DROP TABLE #dates
0 голосов
/ 28 апреля 2011

Видите, запрос прост, но каково ваше требование с датой. Я даю простой запрос, который даст вам идею, и я использую временную таблицу:

Create Table #Transection
(
    ID int Identity(1,1) not null,Item_Number varchar(20),Transection_Date datetime,Quantity_Available decimal(10,2)
)

insert into #Transection (Item_Number)  (Select ItemNumber from Items)

Declare @Product varchar(20),@Next_Product Cursor, @Item varchar(20),@Quantity decimal(10,2)
set  @Next_Product= CURSOR FOR Select Item_Number from #Transection open @Next_Product Fetch Next from @Next_Product into @Product

    While @@Fetch_Status=0
        Begin
            set @Item=(Select ItemNumber from  ItemTransection where ItemNumber= @Product)
                if is not null
                    Begin
                        Set @Quantity=(Select top 1 Items.Quantityonhand -ItemsTrasection.Quant as Quantity from Items Join
                                       ItemsTrasection on ItemsTrasection.ItemNumber=Items.ItemNumber where ItemsTrasection.ItemNumber=@Item order by ItemsTrasection.TransDate desc)
                        update #Transection set Transection_Date=(Select top 1 TransDate from ItemsTrasection where ItemNumber=@Item order by TransDate desc), Quantity=@Quantity
                            where Item_Number=@Item
                    End
                Else
                    Begin
                        update #Transection set Transection_Date=(Select top 1 TransDate from Items where ItemNumber=@Item ), Quantity=(Select top 1 from Items where ItemNumber=@Item )
                            where Item_Number=@Item
                    End
        End
Select * from #Transection
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...