2016-04-25 4 views
0

Мне интересно, может ли кто-нибудь помочь мне с любым или всем из этого кода ниже. Я заработал, но для меня это кажется неэффективным и, вероятно, довольно медленным, чем оптимальным.Есть ли более эффективный/элегантный способ написать этот код, который у меня есть?

базисную о необходимости этого кода в первую очередь:

У меня есть таблица доставки записей, которые не включают в себя соответствующий номер счета-фактуры. Я просмотрел все столы, и я продолжаю это делать. Фактически, только сегодня утром я обнаружил, что если сальник был сгенерирован, я могу связать столик для доставки с таблицей упаковочного скольжения через этот идентификатор упаковочного листа и взять там номер счета-фактуры. Однако при отсутствии этой ссылки я вынужден угадать. В большинстве случаев это не так сложно, потому что таблица счетов имеет номер, строку и выпуск, которые могут совпадать. Но когда есть несколько отправлений для номера, строки и выпуска (например, когда часть частично отправлена), тогда может быть несколько ответов, только один из которых является правильным. Частично мне помогает присутствие столбца в таблице отгрузки, в котором указывается, какая последовательность дат для этого номера, строки и выпуска, но все еще есть обстоятельства, когда процесс, который я использую для «угадывания», может быть несколько неоднозначным.

Что моя процедура делает это. Во-первых, он создает таблицу данных, которая включает номер счета-фактуры, если для его связывания произошел сбой пакета.

Затем он выгружает все эти данные во вторую таблицу, на этот раз используя - только если счет-фактура был NULL в первой таблице - «угадать» номер счета-фактуры на основе разбиения всех записей доставки на номер, строка, выпуск, последовательность дат и дату, а затем сравнивая это с тем же типом вещи для таблицы счетов и пытайтесь выровнять все по дате.

Наконец, он анализирует эту таблицу и находит все последние значения нулей и в основном сопоставляет их с первой записью любого счета-фактуры для этого номера, строки и выпуска.

Обе догадки добавили символы, чтобы показать, что они, по сути, догадываются.

IF OBJECT_ID('tempdb..#cosTAble') IS NOT NULL 
DROP TABLE #cosTable 

DECLARE @cosTable2 TABLE (
    ID    INT IDENTITY 
    ,co_num   CoNumType 
    ,co_line  CoLineType 
    ,co_release  CoReleaseType 
    ,date_seq  DateSeqType 
    ,ship_date  DateType 
    ,inv_num  NVARCHAR(14) 
    ) 

DECLARE 
    @co_num_ck  CoNumType 
    ,@co_line_ck CoLineType 
    ,@co_release_ck CoReleaseType 

DECLARE @Counter1 INT = 0 

SELECT cos.co_num, cos.co_line, cos.co_release, cos.date_seq, cos.ship_date, cos.qty_invoiced, pck.inv_num 
    INTO #cosTable 
    FROM co_ship cos 
     LEFT JOIN pckitem pck 
      ON cos.pack_num = pck.pack_num 
      AND cos.co_num = pck.co_num 
      AND cos.co_line = pck.co_line 
      AND cos.co_release = pck.co_release 

;WITH cos_Order 
    AS(
     SELECT co_num, co_line, co_release, qty_invoiced, date_seq, ship_date, ROW_NUMBER() OVER (PARTITION BY co_num, co_line, co_release ORDER BY ship_date) AS cosrow 
     FROM co_ship 
     WHERE qty_invoiced > 0 
    ), 

invi_Order 
    AS(
     SELECT inv_num, co_num, co_line, co_release, ROW_NUMBER() OVER (PARTITION BY co_num, co_line, co_release ORDER BY RecordDate) AS invirow 
     FROM inv_item 
     WHERE qty_invoiced > 0 
    ), 

cos_invi 
    AS(
     SELECT cosO.*, inviO.inv_num 
     FROM cos_Order cosO 
      LEFT JOIN invi_Order inviO 
       ON cosO.co_num = inviO.co_num AND cosO.co_line = inviO.co_line AND cosO.cosrow = inviO.invirow) 

INSERT INTO @cosTable2 
SELECT cosT.co_num, cosT.co_line, cosT.co_release, cosT.date_seq, cosT.ship_date, COALESCE(cosT.inv_num,'*'+cosi.inv_num) AS inv_num 
    FROM #cosTable cosT 
    LEFT JOIN cos_invi cosi 
     ON cosT.co_num = cosi.co_num 
     AND cosT.co_line = cosi.co_line 
     AND cosT.co_release = cosi.co_release 
     AND cosT.date_seq = cosi.date_seq 
     AND cosT.ship_date = cosi.ship_date 



WHILE @Counter1 < (SELECT MAX(ID) FROM @cosTable2) BEGIN 
    SET @Counter1 += 1 
    SET @co_num_ck = (SELECT co_num FROM @cosTable2 WHERE ID = @Counter1) 
    SET @co_line_ck = (SELECT co_line FROM @cosTable2 WHERE ID = @Counter1) 
    SET @co_release_ck = (SELECT co_release FROM @cosTable2 WHERE ID = @Counter1) 
    IF EXISTS (SELECT * FROM @cosTable2 WHERE ID = @Counter1 AND inv_num IS NULL) 
     UPDATE @cosTable2 
      SET inv_num = '^' + (SELECT TOP 1 inv_num FROM @cosTable2 WHERE 
          @co_num_ck = co_num AND 
          @co_line_ck = co_line AND 
          @co_release_ck = co_release) 
      WHERE ID = @Counter1 AND inv_num IS NULL 
    END 

SELECT * FROM @cosTable2 
ORDER BY co_num, co_line, co_release, date_seq, ship_date 

ответ

1

Мне кажется, что вы очень стараетесь решить проблему, которая не должна существовать. То, что вы описываете, является, к сожалению, обычной ситуацией, когда процесс становится органически без намерения и конкретного направления по мере роста бизнеса, что сделало невозможным автоматизацию сбора данных. Вам очень нужен набор политик и процедур. Для (очень грубый и простой) пример: 1: Заказ должен существовать до того, как может быть сгенерирован упаковочный листок. 2: упаковочный листок должен быть указан перед выставлением счета-фактуры.
3: счет-фактура создается с использованием данных из упаковочного листка и заказа (что было запрошено, что было выбрано, что мы выставляем) -Возможно, это грубый пример, чтобы проиллюстрировать эту идею. Все данные MUST должны быть введены в соответствующее время или кто-то еще не выполнил свою работу. Это не типичный набор навыков ИТ-отделов для точного и последовательного предоставления хороших данных управления, когда таких данных не существует.

+0

Я подозреваю, что его проблема является прямым следствием неправильного использования ограничений FK и определений данных. Если для таблицы счетов FK есть таблица FK, и если идентификатор упаковочного листка требуется, то счет-фактура просто не может быть создан до тех пор, пока он не будет связан с упаковочным листом. Он должен попытаться решить проблему, почему эта ситуация не работает. Однако даже тогда вам нужно будет идентифицировать эти запутанные записи и исправить их. Но тогда это одно время. – HLGEM

2

Вы находитесь в плохом месте - так как @ craig.white и @HLGEM предлагают, вы унаследовали что-то без достаточных ограничений, чтобы сделать данные правильными или безопасными ... и теперь вам нужно «синтезировать» это. Я получаю, что догадки - это лучшее, что вы можете сделать, и вы можете, по крайней мере, сделать свои догадки разумными по производительности.

После этого вы должны громко кричать, чтобы найти время, чтобы исправить db - применить ограничения, необходимые для предотвращения дальнейшей обработки данных.

Производительность, цикл while - это катастрофа. Вы бы лучше заменить всю эту кашу с помощью одного оператора обновления ... что-то вроде:

update c0 
set inv_nbr = '^' + c1.inv_nbr 
from 
    @cosTable2 c0 
    left outer join 
    (
    select 
     co_num, 
     co_line, 
     co_release, 
     inv_nbr 
    from 
     @cosTable2 
    where 
     inv_nbr is not null 
    group by 
     co_num, 
     co_line, 
     co_release, 
     inv_nbr   
) as c1 
    on 
    c0.co_num = c1.co_num and 
    c0.co_line = c1.co_line and 
    c0.co_release = c1.co_release 
where 
    c0.inv_num is null 

... который делает то же самое, что петля делает, только в одном операторе.

+0

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

+0

@DaveX, нам повезло - многие из нас были на твоей обуви – Clay

+0

Я просто адаптировал эту же конструкцию на совершенно другой процедуре. Работал как шарм. Очень признателен. – DaveX

Смежные вопросы