【问题标题】:CTE query in SQL Server : exit when one row exists in resultSQL Server 中的 CTE 查询:结果中存在一行时退出
【发布时间】:2019-01-19 21:40:18
【问题描述】:

我正在编写一个 SQL Server 程序来优化钢筋切割。我还没有找到最好的方法。似乎是 CTE 请求,但我卡住了。

我尝试写一个存储过程来优化切条。对于我的测试,我必须切割 18 块(3 块 1000 毫米、3 块 1500 毫米、3 块 2500 毫米、3 块 3500 毫米、3 块 4500 毫米和 3 块 6000 毫米),我有 3 种尺寸的钢筋(5500 毫米、7000 毫米和 8500 毫米)。

之后,我会尽可能生成带有任何切口的条形组合。

我尝试了一个 while 循环和一个临时表,这需要我一个半小时。但我认为我可以通过 CTE 请求做得更好......

现在,我必须生成许多条的每一种组合,才能进行 18 次切割。我提出了另一个 CTE 请求,但是当至少一个组合具有所有削减时,我还没有找到停止递归的方法。因此,我的请求找到了超过 1.5 亿个组合,包括 8、9、10、11... 条。它用 18 个小节尝试每个循环。我希望它以 8 条停止(我知道这是我削减所需的最小条数)。而且需要两天多的时间!

我有 2 个临时表,我的条形组合 (#COMBI_BARRE) 具有以下结构:ID_ART:文章标识、颜色、CUT_COMBI:varchar 连接条形组合的剪切 ID:1-2-3- 4..., NB_CUT 一个整数来获取bar中的cut数量,FIRST_CUT 是bar中较小的cut ID。

我有另一个临时表#DET_BAR,其中包含我的剪辑的详细信息,有 2 列:ID_COMBI_BAR 条组合 ID 和 ID_CUT_STR,varchar 中的剪辑 ID(以避免在 CTE 中转换或转换以获得更好的性能)。

我将结果存储在一个名为 Combi 的表中,其中 ID_ART、COLOR、一个 varchar 列 Combi 连接条形组合 ID (1-2-3-4...)、一个 varchar 列 COMBI_CUT 连接ID_CUT (1-2-3-4-5...),NB_BAR 组合中的条数,NB_CUTS:组合中的剪切数,MAX_CUTS 我必须为我的文章和颜色进行的剪切总数.

因为它每条循环一个循环,所以我尝试添加一个存在子句以在循环数与我的所有切割至少有一个组合时停止递归。我知道如果我可以用 8 条来减少 10 条,我一定不能削减。但我收到错误“递归表有多个引用”。

我怎样才能提出我的要求并避免每一个循环?

;WITH Combi (ID_ART, COLOR, COMBI, COMBI_CUT, NB_BAR, NB_CUTS, MAX_CUTS)
AS
( SELECT C.ID_ART, 
        C.COLOR,
      '-' + ID_COMBI_BAR_STR + '-',
         '-' + C.CUT_COMBI + '-',
         1,
         C.NB_CUTS,
         ISNULL(MAXI.CUT_NUM,0)
FROM #COMBI_BARRE C with(nolock)
outer apply (select top 1 D.CUT_NUM
             from #DEBITS D
             where D.ID_ART = C.ID_ART
             and D.COLOR= C.COLOR
             order by D.NUM_OCC_DEB desc) MAXI
WHERE C.FIRST_CUT = 1
UNION ALL
SELECT C.ID_ART, 
             C.COLOR, 
             Combi.COMBI  + ID_COMBI_BAR_STR + '-',
             Combi.COMBI_CUT+ C.CUT_COMBI + '-',
             Combi.NB_BAR+ 1,
             Combi.NB_CUTS+ C.NB_CUTS,
             Combi.MAX_CUTS
  FROM #COMBI_BARRE C with(nolock)
  INNER JOIN Combi  on C.ID_ART = Combi.ID_ART
                          and C.COLOR= Combi.COLOR
  where C.FIRST_CUT > Combi.NB_BAR
  and Combi.NB_CUTS+ C.NB_CUTS<= Combi.MAX_CUTS
  and NOT EXISTS(select * from #DET_BAR D with(nolock)
                           where D.ID_COMBI_BAR = C.ID_COMBI_BAR
                           and PATINDEX(D.ID_CUT_STR, Combi.COMBI_CUT) > 0)
 and NOT EXISTS(select top 1 * from Combi Combi2 where Combi2.ID_ART = C.ID_ART and Combi2.COLOR = C.COLOR and Combi2.NB_CUTS = Combi2.MAX_CUTS)
)
select * from Combi 

【问题讨论】:

    标签: sql sql-server performance recursion common-table-expression


    【解决方案1】:

    这是装箱问题的一种变体。该搜索词可能会帮助您找到正确的方向。

    另外,您可以访问我的Bin Packing 页面,该页面提供了几种解决您问题的更简化版本的方法。

    一个小警告:链接的文章不使用任何(递归)CTE,因此它们不会回答您的特定 CTE 问题。

    【讨论】:

    • 谢谢你的回答...它帮助我搜索。你的代码很有趣。,.. 如果我能按照你的方式做到这一点,我会通知你(在我的情况下,我有三个大小的 bin,我必须调整我的代码)
    猜你喜欢
    • 1970-01-01
    • 2017-07-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-05-03
    • 2014-10-15
    • 2010-11-03
    • 2022-01-07
    相关资源
    最近更新 更多