2014-09-08 4 views
1

오랫동안 질문하는 것 같지만 일부 샘플 SQL을 넣었으므로 지금보고 싶은 것을 얻을 수 있습니다.특정 날짜에 대한 올바른 감사 세부 정보 가져 오기

기본적으로 현재 가격이있는 재고 테이블이 있습니다. 가격이 변경되면 트리거는 이전 가격으로 감사 테이블에 레코드를 생성하고 validTo 필드를 이전 날짜로 설정합니다. 오늘 사과 가격을 1시 10 분에서 1시 20 분으로 바꿀 경우, 1시 10 분은 하루 전날이고 1시 20 분은 어제 자정까지 올랐다고 가정합니다.

모두 좋습니다 ... 그래서 생각했습니다. 내 문제는 이제 모든 판매를 가져 와서 판매일에 해당 재고 항목에 대한 가격이 인출되기를 원한다는 것입니다. 내 예에서 망고처럼 일부 가격은 변하지 않았으므로 현재 가격 만이 가격이므로 추가 할 감사 기록이 없습니다.

제가 크로스 테이블을 판매 테이블에 적용했지만 문제가 있다고 생각했습니다. 여기

은 .. 지금까지 ... 여기에 변경된 가격을 당겨까지

drop table #CurrentStock 
    drop table #AuditTable 
    drop table #Sales 

    create table #CurrentStock 
    (
     StockID  int identity , 
     Stock  varchar(50), 
     Quantity int, 
     Price  decimal(5,2), 
     Supplier varchar(50) 
    ) 

    go 

    create table #AuditTable 
    (
     AuditID int identity, 
     StockID int, 
     Price decimal(5,2), 
     ValidTo date 
    ) 

    go 

    create table #sales 
    (
     SaleID int identity, 
     StockID int, 
     AmountSold int, 
     DateSold date 
    ) 

    --Insert 4 stock items and the current price 
    insert into #CurrentStock values ('Apple', 200, 1.50, 'Jones'); 
    insert into #CurrentStock values ('Banana', 300, 1.10, 'Smiths'); 
    insert into #CurrentStock values ('Oranges', 100, 1.75, 'Ables'); 
    insert into #CurrentStock values ('Pears', 400, 2.50, 'Jones'); 
    insert into #CurrentStock values ('Mango', 350, 3.50, 'Jacks'); -- Note this has no audit as the price hasnt changed 

    --Insert the Price Changes for the stock 
    -- Note the ValidTo field... is up to and including that date so for the first item for apple 
    -- the price of 1:10 was valid up to and including 2014-05-01. The next price change of 1.18 
    -- would then be valid from 2014-05-02 up to and including 2014-05-07 

    insert into #auditTable values (1, 1.10, '2014-05-01'); 
    insert into #auditTable values (1, 1.18, '2014-05-07'); 
    insert into #auditTable values (1, 1.22, '2014-05-18'); 
    insert into #auditTable values (2, 1.11, '2014-05-11'); 
    insert into #auditTable values (2, 1.14, '2014-05-17'); 
    insert into #auditTable values (2, 1.16, '2014-05-23'); 
    insert into #auditTable values (2, 1.12, '2014-05-28'); 
    insert into #auditTable values (3, 1.86, '2014-05-17'); 
    insert into #auditTable values (3, 1.92, '2014-05-20'); 
    insert into #auditTable values (4, 2.62, '2014-05-11'); 
    insert into #auditTable values (4, 2.67, '2014-05-12'); 
    insert into #auditTable values (4, 2.92, '2014-05-20'); 

    -- Create Some Sales 

    -- Apples 
    insert #sales values (1,2,'2014-05-01'); -- price should be 1.10 
    insert #sales values (1,3,'2014-05-03'); -- price should be 1.18 
    insert #sales values (1,1,'2014-05-08'); -- price should be 1.22 
    insert #sales values (1,4,'2014-05-11'); -- price should be 1.22 
    insert #sales values (1,3,'2014-05-14'); -- price should be 1.22 
    insert #sales values (1,4,'2014-05-20'); -- price should be current price in stock table 

    -- Bananna 
    insert #sales values (2,2,'2014-05-01'); -- price should be 1.11 
    insert #sales values (2,5,'2014-05-10'); -- price should be 1.11 
    insert #sales values (2,2,'2014-05-12'); -- price should be 1.14 
    insert #sales values (2,4,'2014-05-17'); -- price should be 1.14 
    insert #sales values (2,2,'2014-05-25'); -- price should be 1.12 

    -- Now I want to get the stock that has a price change after the 2014-05-15 
    -- If there is no price change like in the case of Mango then we want the current Price 
    select * from 
    (
     SELECT 
      StockId, 
      Rank() OVER (Partition By StockId Order By ValidTo Desc) as RowNum,  
      Price, 
      ValidTo 
     FROM 
      #auditTable aud 
     WHERE 
       ValidTo > '2014-05-15' -- filter out the records that we dont need 

     UNION 

     SELECT 
      StockId, 
      0 as RowNum, -- make this Row num 0 so we can group on them   
      Price, 
      cast(GETDATE() as DATE) 
     FROM 
      #CurrentStock cs 
    ) stockList order by StockID,RowNum 

그래서 모든 좋은 샘플 코드입니다. 이제 문제는 제가 모든 매출을 얻고 주식에 가입하고 그 주식이 판매 시점에 있었던 가격을 얻고 싶다는 것입니다. 그래서 위의 쿼리를 CTE 또는 그와 비슷한 것으로 포장해야합니다. 나는 십자가에 신청할 수 있습니다.

아마 날짜와 주식 ID를 가져 와서 가격이 가장 좋을 수도 있고 그걸 적용하는 기능을 만들 수도 있습니다.하지만 지금은 함수를 만들 권한이 없습니다. 먼 길을 취할 필요가있다.

크게 감사합니다 어떤 도움을 ... 나는이 당신을 위해 무엇을 찾고있는 생각 M

답변

0

어때?

select * 
from #sales s 
cross apply 
(
    select top 1 cs.StockID 
     , cs.Stock 
     , ISNULL(a.ValidTo, getdate()) as ValidTo 
     , ISNULL(a.Price, cs.Price) as Price 
    from #CurrentStock cs 
    left join #AuditTable a on a.StockID = cs.StockID 
    where s.DateSold <= ISNULL(a.ValidTo, getdate()) 
     and s.StockID = cs.StockID 
    order by ISNULL(a.ValidTo, getdate()) 
) x 
+0

안녕하세요 숀, 그 대답을 받아 들일 수 없어 간단하고 나를 어리석은 LOL 보이게 :-) .. 그냥 따로 따로하지만 트릭을 할 것으로 보인다 ... 나는 자신을 시도했지만 그냥 매듭 있어요. 내가 너에게 돌아가서 고마워. – MightyBelle

+0

LOL. 나는 네가 바보처럼 보이게한다고 말하지 않을거야.문제에 너무 가까워서 해결책을 보는 것이 때때로 어렵습니다. 바라기를 이것은 당신을 위해 작동합니다. –

+0

멋진 멋지고 매끄러운 솔루션 Sean ... 네, 100 % 가까이 있습니다. 난 단지 내 복잡한 응용 프로그램에 복고풍 솔루션을 장착하고 치료를 ... 더하기 그게 내 수백만의 레코드를 다루는대로 빨리 .. 감사합니다 .. 많이 감사 - M – MightyBelle

0

간주한다. 그것은 당신의 감사 필터를 얻고 임시 테이블 (#TempAudit)에 저장하도록 선택 ..

  select * 
     into #TempAudit -- saved into temp table called #TempAudit 
     from 
     (
      SELECT 
       StockId, 
       Rank() OVER (Partition By StockId Order By ValidTo Desc) as RowNum,  
       Price, 
       ValidTo 
      FROM 
       #auditTable aud 
      WHERE 
        ValidTo > '2014-05-15' -- filter out the records that we dont need 

      UNION 

      SELECT 
       StockId, 
       0 as RowNum, -- make this Row num 0 so we can group on them   
       Price, 
       cast(GETDATE() as DATE) 
      FROM 
       #CurrentStock cs 
     ) stockList 
     order by StockID,RowNum 
#TempAudit 테이블을 사용

..

수정은 사용 어쨌든 하나 개의 옵션 ..

입니다 :

 select * 
from #Sales sales 
    inner join 
    (
     select ta1.StockId, ta1.RowNum, ta1.Price 
     , ta1.ValidTo as ValidDateFromInclusive 
     , ISNULL(ta2.ValidTo, '9999-12-31') as ValidDateToExclusive 
     from #TempAudit ta1 
    left outer join 
     #TempAudit ta2 
    on ta1.stockId = ta2.stockid and ta1.RowNum - 1 = ta2.rownum 
    union all 
    select StockId, RowNum+1, Price, '1900-01-01' as ValidDateFromInclusive, ValidTo as ValidDateToExclusive 
     from #tempAudit ta 
     where rownum = (select max(rownum) from #tempAudit where StockId = ta.StockId) 
    ) AuditWithDates 
    on sales.StockId = AuditWithDates.StockId 
     and (sales.DateSold >= AuditWithDates.ValidDateFromInclusive and sales.DateSold < AuditWithDates.ValidDateToExclusive) 
order by sales.SaleID 
+0

안녕 TM .. SEANS 아래에 있지만 지금을 비교 ... 임시 테이블을 사용하여 매우 유사 도움을 주셔서 감사합니다 .. ... 다시 한번 감사드립니다 .. – MightyBelle

+0

TM ... 다시 한번 감사드립니다 ... 나는 Temans 테이블을 필요로하지 않았기 때문에 Seans의 대답으로 갔다. 그러나 이것을 보아 주셔서 고마워. M – MightyBelle

+0

BTW. .. 나는 Seans이 확실히 elegent 인 것처럼 대답을 확인하는 것을 도울 수 없다. 나는 가격이 샘플 데이터에 따라 다르다는 것을 알았습니다. 감사 쿼리에서 'ValidTo>'2014-05-15 '제한을 제거하고 Seans과 내 답변을 실행하십시오. 'SaleID = 3'은 'Seans is 1.22','mine is 1.18', Seans는 1.14, Mine is 1.11은 SaleID = 9로 가격이 다릅니다. 어떤 답변이 맞는지는 확실치 않지만 체크 아웃을 원할 수 있습니다. 내 스크립트가 피드백 목적에 맞지 않으면 알려주십시오. 감사 검색으로 인해 답변을 수정했습니다. – Tak

관련 문제