Получить первую доступную дату (максимальная дата), присоединившись к таблице ранжированных ASC на основе дат - PullRequest
0 голосов
/ 31 октября 2019

У меня есть набор данных, ниже которого я создал, чтобы эмулировать, как выглядят мои живые данные. Я пытаюсь вывести ПОСЛЕДНИЕ стандартные затраты на основе даты по возрастанию из CTE стандартной стоимости, где учитываются только те даты, которые предшествуют дате транзакции инвентаризации. Пока у меня есть вот что: оно работает, но не очень эффективно в зависимости от плана выполнения.

CREATE TABLE stdcosts
(item varchar(20) not null,
indt date not null,
rev integer not null,
[MC00.010] money default 0,
[OC00.000] money default 0,
[GC00.025] money default 0,
[MS00.010] money default 0) ;

 INSERT INTO stdcosts
VALUES
('201226-03','02/26/2019',1,2000,0,100,50),
('201226-03','09/07/2019',2,700,0,0,50),
('201226-03','10/07/2019',3,500,0,20,10)

CREATE TABLE inventoryOH 
(item varchar(20) not null,
 warehouse varchar(8) not null,
 TransDate date not null,
 seq integer not null default 1,
 owner varchar(10) ,
 project varchar(10),
 orderID varchar(10),
 onHand integer default 0,
 Age bigint,
 costMethod varchar(15) ,
 WVG_flag varchar(1),
 WVG char(4),
  rowno int );

 INSERT INTO inventoryOH
 VALUES
 ('201226-03','B','6/18/2019',1,'','','NPO312979',5,134,'STANDARD','N','',1),
 ('201226-03','B','9/3/2019',1,'','','NPO315960',14,57,'STANDARD','N','',2),
 ('201226-03','B','9/23/2019',1,'','','SFC037624',1,37,'STANDARD','N','',3),
 ('201226-03','B','10/1/2019',1,'','','NPO316472',6,29,'STANDARD','N','',4);

Вывод:

SELECT i.*, s.*
FROM inventoryOH i
LEFT JOIN stdcosts s
    ON s.item = i.item
    AND s.indt <= i.TransDate
    AND s.rev IN (SELECT MAX(s1.rev)
                     FROM stdcosts s1
                      WHERE s1.item = s.item
                      AND s1.indt <= i.TransDate)

Интересно, есть ли у кого-нибудь способоптимизируйте это, используя номер ранга / строки или дополнительные методы, чтобы ускорить процесс.

ссылка -> http://sqlfiddle.com/#!18/2b4865/2

1 Ответ

1 голос
/ 01 ноября 2019

Вы можете использовать OUTER APPLY для выполнения бокового соединения.

Для каждой строки в inventoryOH нам нужно найти одну строку из stdcosts, которая имеет тот же item, который имеет indt в * или выше TransDate и который имеет максимум rev.

SELECT
    inventoryOH.*
    ,Costs.*
FROM
    inventoryOH
    OUTER APPLY
    (
        SELECT TOP(1)
            item
            ,indt
            ,rev
            ,[MC00.010]
            ,[OC00.000]
            ,[GC00.025]
            ,[MS00.010]
        FROM stdcosts
        WHERE
            stdcosts.item = inventoryOH.item
            AND stdcosts.indt <= inventoryOH.TransDate
        ORDER BY
            stdcosts.rev DESC
    ) AS Costs
;

Для эффективной работы необходимо создать индекс в таблице stdcosts для (item, indt) include (rev, [MC00.010],[OC00.000],[GC00.025],[MS00.010]). Порядок столбцов в индексе важен.

Я не уверен, какой должна быть логика вокруг значений rev, но если вам нужна последняя строка, основанная только на indt (не на rev), тогда сортировка должна быть по indt: ORDER BY stdcosts.indt DESC. Это также будет работать более эффективно с предложенным индексом.

...