是否有更高效/更优雅的方式来编写我的代码?

时间:2016-04-25 17:46:22

标签: tsql

我想知道是否有人可以帮助我解决下面的任何或所有代码问题。我已经让它工作了,但对我来说似乎效率低下,而且可能比最佳速度慢一点。

首先是关于此代码必要性的一些基本背景:

我有一张运输记录表,其中不包含相应的发票编号。我看了看表,我继续这样做。事实上,仅在今天早上我发现如果已生成装箱单,我可以通过装箱单ID将装运单链接到装箱单,并从那里抓取发票号。然而,如果没有这个链接,我不得不猜测。在大多数情况下,这并不是非常困难,因为发票表具有可以匹配的数字,行和版本。但是当数量,线路和发布有多个货件时(例如,当一条线路被部分运送时),则可能有多个答案,其中只有一个是正确的。我在运输表中列出了一个列,说明该数字,行和释放的日期顺序,但部分原因仍然是我用于“猜测”的过程可能有些含糊不清。

我的程序是做什么的。首先,它会创建一个数据表,其中包含发票编号,如果有一个包装单将其链接起来。

接下来,它将所有数据转储到第二个表中,这次使用 - 仅当第一个表中的发票为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

2 个答案:

答案 0 :(得分:2)

你处在一个不好的地方 - 正如@ craig.white和@HLGEM建议的那样,你继承了没有足够限制的东西来使数据正确或安全......现在你必须“合成”它。我得到的猜测是你能做的最好的,你可以,至少让你的猜测在性能方面合理。

之后,你应该大声尖叫以获得一些时间来修复数据库 - 应用所需的约束来防止数据的进一步破坏。

性能方面,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

...循环所做的事情与单一语句相同。

答案 1 :(得分:1)

在我看来,你正在努力解决一个不应该存在的问题。你所描述的是一个不幸的常见情况,即随着业务的增长,一个过程在没有意图和具体方向的情况下有机地增长,这使得数据提取几乎不可能实现自动化。你非常需要一套政策和程序 - 对于(非常粗略和简单)的例子: 1:在生成装箱单之前必须存在订单。 2:在生成发票之前,必须存在装箱单 3:使用装箱单和订单中的数据创建发票(请求的内容,选择的内容,我们收取的费用) - 再说一遍,这只是一个粗略的例子来说明这个想法。 所有数据必须在适当的时间输入或有人没有完成他们的工作。 当这些数据不存在时,准确一致地提供管理良好数据并不是IT部门的典型技能。