2016-04-25 13 views
0

誰かがこのコードの一部または全部で私を助けてくれるのだろうかと思っています。私はそれを動作させましたが、私にとっては非効率的で、おそらく最適よりもかなり遅いでしょう。私は持っているこのコードを書くより効率的/エレガントな方法はありますか?

最初の場所でこのコードの必要性についていくつかの基本的な背景:

私は、対応する請求書番号が含まれていない出荷レコードのテーブルを持っています。私はテーブルをすべて見てきました。私は引き続きそうしています。実際には、今朝だけ私は、梱包伝票が生成された場合、その梱包伝票IDを介して出荷伝票を梱包伝票にリンクし、そこから請求書番号を取得できることを発見しました。しかし、そのリンクがなければ、私は推測する必要があります。ほとんどの場合、それは非常に難しいことではありません。なぜなら、請求書テーブルには数字、行、およびリリースが一致する可能性があるからです。しかし、番号、ライン、リリース(たとえば、ラインが部分的に出荷されている場合など)に複数の出荷がある場合は、複数の回答がありますが、そのうちの1つだけが正しいです。私は部分的に出荷表の列が存在することによって部分的に助けられています。これは、日付シーケンスがその番号、行およびリリースのものであることを示していますが、私が "推測"のために使用するプロセスが多少あいまいな状況があります。

これは私の手続きです。まず、リンクするパック伝票があれば、請求書番号を含むデータテーブルを作成します。

次に、すべてのデータを2番目のテーブルにダンプします。今回は、最初のテーブルで請求書が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:請求書は、梱包明細書および注文書のデータを使用して作成されています(要求されたもの、選択されたもの、請求するもの) -Again、これはアイデアを説明するためのものです。 すべてのデータMUSTは、適切な時期に入力されるか、誰かが仕事をしていないこと。 IT部門の典型的なスキルセットでは、そのようなデータが存在しない場合に、管理上適切なデータを正確かつ一貫して提供することはできません。

+0

私は彼の問題がFK制約とデータ定義を正しく使用していないという直接的な結果であると思われます。請求書の梱包伝票にFKがあり、梱包伝票IDが必要な場合は、梱包伝票に関連するまで請求書を登録することはできません。彼は、なぜこのような状況が存在しないのかという問題を解決しようとしているはずです。しかし、それでもなお、これらの現在の混乱したレコードを特定し、修正する必要があります。しかしそれは一度の修正です。 – 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

関連する問題