2014-11-15 4 views
2

재고 목록이 있습니다. 재고 테이블 SQL :매출 원가 계산 방법

CREATE TABLE INVENTORY 
(
    INVENTORY_ID    SERIAL PRIMARY KEY, 
    INVENTORY_DATE   date NOT NULL, 
    ITEM_NAME    text NOT NULL, 
    PURCHASED_QUANTITY  INTEGER DEFAULT 0, 
    SOLD_QUANTITY   INTEGER DEFAULT 0, 
    AMOUNT     MONEY NOT NULL, 
    TOTAL     MONEY NOT NULL  
); 

INSERT INTO INVENTORY(INVENTORY_DATE, ITEM_NAME, PURCHASED_QUANTITY, SOLD_QUANTITY, AMOUNT, TOTAL) 
SELECT '1/1/2014'::date, 'ITEM-001', 10, NULL, 100, 1000 UNION ALL 
SELECT '1/2/2014'::date, 'ITEM-001', NULL, 2, 200, 400 UNION ALL 
SELECT '1/3/2014'::date, 'ITEM-001', 20, NULL, 110, 2200 UNION ALL 
SELECT '1/4/2014'::date, 'ITEM-001', NULL, 4, 200, 800 UNION ALL 
SELECT '1/5/2014'::date, 'ITEM-001', 20, NULL, 80, 1600; 

표는이 같은 기능을 만들려고하고

SELECT * FROM INVENTORY; 

INVENTORY_DATE ITEM_NAME PURCHASED_QUANTITY SOLD QUANTITY  AMOUNT TOTAL 
----------------------------------------------------------------------------------------- 
1/1/2014   ITEM-001  10          $100  $1000 
1/2/2014   ITEM-001       2     $200  $400 
1/3/2014   ITEM-001  20          $110  $2200 
1/4/2014   ITEM-001       4     $200  $800 
1/5/2014   ITEM-001  20          $80  $1600 

: 그래서

CREATE FUNCTION GET_FIFO_COGS(ITEM_NAME TEXT, QUANTITY INTEGER) 
RETURNS MONEY 
AS 
$$ 
BEGIN 

END 
$$ 
LANGUAGE "PLPGSQL"; 

것을, 내가 할 수있는 :

SELECT * FROM GET_FIFO_COGS('ITEM-001', 4) --> $400 
--Remaining 4. Each for $100. 

SELECT * FROM GET_FIFO_COGS('ITEM-001', 12) --> $1280 
--4 for $100, 8 for 110. 

SELECT * FROM GET_FIFO_COGS('ITEM-001', 34) --> $3400 
--4 for $100, 20 for $110, 10 for $80. 

I 이 질문을 향상시킬 수있는 바른 길. 나는 SQL을 배우고 있는데,이 문제는 나에게 문제를 일으키고 있으며 나는이 문제를 해결할 수 없다.

답변

3

SQL Fiddle

용액에 접근 generate_series를 사용하는 단일 항목 n 행에 n 항목과 각 행을 확장하는 것이다. 그런 다음 purchasedsold에 대한 두 개의 별도 세트를 작성하십시오. 각 세트의 행은 inventory_id 순서로 번호가 매겨져 있으므로 이미 soldpurchased 항목을 제거 할 수 있습니다. 그런 다음 order byinventory_idlimit을 수량에 입력하십시오.

create or replace function get_fifo_cogs(_item_name text, _quantity int) 
returns money as $$ 
    with inventory as (
     select 
      inventory_id, inventory_date, 
      generate_series(1, greatest(purchased_quantity, sold_quantity)), 
      amount, 
      purchased_quantity is not null as purchased 
     from inventory 
     where item_name = _item_name 
    ), purchased as (
     select *, row_number() over(order by inventory_id) as rn 
     from inventory 
     where purchased 
    ), sold as (
     select *, row_number() over(order by inventory_id) as rn 
     from inventory 
     where not purchased 
    ) 
    select sum(amount) as cogs 
    from (
     select amount 
     from purchased 
     where not exists (
      select 1 
      from sold 
      where rn = purchased.rn 
     ) 
     order by inventory_id 
     limit _quantity 
    ) s; 
$$ language sql; 

select cogs from get_fifo_cogs('ITEM-001', 4) gfc(cogs); 
    cogs 
--------- 
$400.00 
(1 row) 

select cogs from get_fifo_cogs('ITEM-001', 12) gfc(cogs); 
    cogs  
----------- 
$1,280.00 
(1 row) 

select cogs from get_fifo_cogs('ITEM-001', 34) gfc(cogs); 
    cogs  
----------- 
$3,400.00 

하거나

select get_fifo_cogs('ITEM-001', 4) as cogs; 
+0

감사로 사용합니다. 완벽하게 작동합니다. 인벤토리별로 내림차순으로 주문하면 LIFO 값을 얻을 수 있습니까? – Nancy

+0

@Nancy 분석하지 않았음에도 불구하고 그렇습니다. –

+0

감사합니다. 나는 여기서 시험 할 것이다. + (1) 코드를 멋지게 설명합니다. – Nancy