SQL Join, сравнивая меры или цикл с курсорами? - PullRequest
0 голосов
/ 21 ноября 2018

Чтобы проверить, выполняются ли поставки вовремя, мне нужно сопоставить документы поставки с линиями графика поставок (SchLin) на основе сравнения между обязательным количеством (ReqQty) и доставленным количеством (DlvQty).

Документы по доставке имеют ссылку на PO и POItm, но не на SchLin.Как только Документ Доставки назначен Строке Графика, я могу вычислить Дельту Доставки (DlvDelta) как количество дней, когда он был доставлен рано или поздно по сравнению с требованием (ReqDate).

Примеры двух базовых таблиц

Строки расписания

PO  POItm   SchLin  ReqDate ReqQty
123 1       1       10/11   20
123 1       2       30/11   30
124 2       1       15/12   10
124 2       2       24/12   15

Документы доставки

Doc Item    PO  POItm   DlvDate DlvQty
810 1       123 1       29/10   12
816 1       123 1       02/11   07
823 1       123 1       04/11   13
828 1       123 1       06/11   08
856 1       123 1       10/11   05
873 1       123 1       14/11   09
902 1       124 2       27/11   05
908 1       124 2       30/11   07
911 1       124 2       08/12   08
923 1       124 2       27/12   09

Важно: Строки и поставки графика должны иметь одинаковые PO и POItm.Другая логика для связывания заключается в суммировании DlvQty, пока мы не достигнем (или не превысим) ReqQty.Эти поставки затем связываются со строкой графика.Последующие поставки используются для следующих строк графика.Доставка должна соответствовать только одной строке графика.

После сравнения ReqQty и DlvQty назначения должны привести к следующему:

Результат

Doc Item    PO  POItm   Schlin  ReqDate DlvDate DlvDelta
810 1       123 1       1       10/11   29/10   -11
816 1       123 1       1       10/11   02/11   -08
823 1       123 1       1       10/11   04/11   -06
828 1       123 1       2       30/11   06/11   -24
856 1       123 1       2       30/11   10/11   -20
873 1       123 1       2       30/11   14/11   -16
902 1       124 2       1       15/12   27/11   -18
908 1       124 2       1       15/12   30/11   -15
911 1       124 2       2       24/12   08/12   -16
923 1       124 2       2       24/12   27/12   +03

Наверхдо сих пор я делал это с помощью циклов с использованием курсоров, но производительность довольно низкая.

Есть ли другой способ в SQL (сценарии), например, использовать объединения, сравнивая меры для достижения того же результата?

С уважением,

Эрик

1 Ответ

0 голосов
/ 22 ноября 2018

Если вы можете выразить правило для сопоставления доставки со строкой графика, вы можете получить нужные результаты в одном запросе.И, да, я обещаю, что это будет быстрее (и проще), чем выполнять ту же логику в циклах на курсорах.

Я не могу воспроизвести ваши точные результаты, потому что я не совсем понимаю, как соотносятся две таблицы.Надеемся, что из приведенного ниже кода вы сможете понять это, изменив критерии объединения.

У меня нет вашей СУБД.Мой код использует SQLite, который имеет свои собственные специфические функции даты.Вам придется заменить те, которые предоставляет ваша система.В любом случае, я не могу рекомендовать 5-символьные строки для дат.Используйте тип datetime, если он у вас есть, и включайте 4-значные годы независимо.Сколько еще дней между Рождеством и Новым годом?

create table S (
    PO int not NULL,
    POItm int not NULL,
    SchLin int not NULL,
    ReqDate char not NULL, 
    ReqQty int not NULL,
    primary key (PO, POItm, SchLin)
    );

insert into S values
(123, 1,       1,       '10/11',   20 ), 
(123, 1,       2,       '30/11',   30 ), 
(124, 2,       1,       '15/12',   10 ), 
(124, 2,       2,       '24/12',   15 );

create table D (
       Doc int not NULL, 
       Item int not NULL, 
       PO int not NULL, 
       POItm int not NULL, 
       DlvDate char not NULL, 
       DlvQty int not NULL,
       primary key (Doc, Item)
); 

insert into D values 
(810, 1,       123, 1,       '29/10',   12 ), 
(816, 1,       123, 1,       '02/11',   07 ), 
(823, 1,       123, 1,       '04/11',   13 ), 
(828, 1,       123, 1,       '06/11',   08 ), 
(856, 1,       123, 1,       '10/11',   05 ), 
(873, 1,       123, 1,       '14/11',   09 ), 
(902, 1,       124, 2,       '27/11',   05 ), 
(908, 1,       124, 2,       '30/11',   07 ), 
(911, 1,       124, 2,       '08/12',   08 ), 
(923, 1,       124, 2,       '27/12',   09 );

select D.Doc, D.Item, D.PO, S.SchLin, S.ReqDate, D.DlvDate
, cast(
    julianday('2018-' || substr(DlvDate, 4,2) || '-' || substr(DlvDate, 1,2))
  - julianday('2018-' || substr(ReqDate, 4,2) || '-' || substr(ReqDate, 1,2))
  as int) as DlvDelta
from S join D on S.PO = D.PO and S.POItm = D.POItm
;

Результат:

Doc         Item        PO          SchLin      ReqDate     DlvDate     DlvDelta  
----------  ----------  ----------  ----------  ----------  ----------  ----------
810         1           123         1           10/11       29/10       -12       
810         1           123         2           30/11       29/10       -32       
816         1           123         1           10/11       02/11       -8        
816         1           123         2           30/11       02/11       -28       
823         1           123         1           10/11       04/11       -6        
823         1           123         2           30/11       04/11       -26       
828         1           123         1           10/11       06/11       -4        
828         1           123         2           30/11       06/11       -24       
856         1           123         1           10/11       10/11       0         
856         1           123         2           30/11       10/11       -20       
873         1           123         1           10/11       14/11       4         
873         1           123         2           30/11       14/11       -16       
902         1           124         1           15/12       27/11       -18       
902         1           124         2           24/12       27/11       -27       
908         1           124         1           15/12       30/11       -15       
908         1           124         2           24/12       30/11       -24       
911         1           124         1           15/12       08/12       -7        
911         1           124         2           24/12       08/12       -16       
923         1           124         1           15/12       27/12       12        
923         1           124         2           24/12       27/12       3         
...