Sqlserver
 sql >> Cơ Sở Dữ Liệu >  >> RDS >> Sqlserver

Định giá hàng tồn kho dựa trên FIFO trong SQL Server

Đáng ngạc nhiên là khó khăn để nhận được đúng. Tôi nghi ngờ sẽ dễ dàng hơn bằng cách sử dụng SQL Server 2012 hỗ trợ chạy tính tổng trong các chức năng cửa sổ. Nhưng dù sao:

declare @Stock table (Item char(3) not null,[Date] datetime not null,TxnType varchar(3) not null,Qty int not null,Price decimal(10,2) null)
insert into @Stock(Item ,  [Date] ,        TxnType, Qty,  Price) values
('ABC','20120401','IN',    200, 750.00),
('ABC','20120405','OUT',   100 ,null  ),
('ABC','20120410','IN',     50, 700.00),
('ABC','20120416','IN',     75, 800.00),
('ABC','20120425','OUT',   175, null  ),
('XYZ','20120402','IN',    150, 350.00),
('XYZ','20120408','OUT',   120 ,null  ),
('XYZ','20120412','OUT',    10 ,null  ),
('XYZ','20120424','IN',     90, 340.00);

;WITH OrderedIn as (
    select *,ROW_NUMBER() OVER (PARTITION BY Item ORDER BY [DATE]) as rn
    from @Stock
    where TxnType = 'IN'
), RunningTotals as (
    select Item,Qty,Price,Qty as Total,0 as PrevTotal,rn from OrderedIn where rn = 1
    union all
    select rt.Item,oi.Qty,oi.Price,rt.Total + oi.Qty,rt.Total,oi.rn
    from
        RunningTotals rt
            inner join
        OrderedIn oi
            on
                rt.Item = oi.Item and
                rt.rn = oi.rn - 1
), TotalOut as (
    select Item,SUM(Qty) as Qty from @Stock where TxnType='OUT' group by Item
)
select
    rt.Item,SUM(CASE WHEN PrevTotal > out.Qty THEN rt.Qty ELSE rt.Total - out.Qty END * Price)
from
    RunningTotals rt
        inner join
    TotalOut out
        on
            rt.Item = out.Item
where
    rt.Total > out.Qty
group by rt.Item

Quan sát đầu tiên là chúng ta không cần làm bất cứ điều gì đặc biệt cho OUT giao dịch - chúng tôi chỉ cần biết tổng số lượng. Đó là những gì TotalOut CTE tính toán. Hai CTE đầu tiên hoạt động với IN giao dịch và tính toán "khoảng thời gian" của mỗi cổ phiếu đại diện - thay đổi truy vấn cuối cùng thành chỉ select * from RunningTotals để cảm nhận điều đó.

SELECT cuối cùng câu lệnh tìm các hàng chưa được sử dụng hết bởi các giao dịch gửi đi và sau đó quyết định xem đó là toàn bộ số lượng của giao dịch đến đó hay đó là giao dịch nằm trong tổng số gửi đi.



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Làm cách nào chúng ta có thể tách tên tiếng Ả Rập khỏi một cột trong SQL Server 2012?

  2. pyodbc không thể kết nối với cơ sở dữ liệu

  3. Chèn dữ liệu không trùng lặp từ bảng mẹ vào bảng con trong SQL server 2008

  4. Thêm truy vấn bên trong không thay đổi kế hoạch thực thi

  5. SQL Server 2005:Chèn nhiều hàng với một truy vấn