根据两列的范围重复行

Repeat the rows based on the Range of two columns

我已经为以下数据和我尝试过的查询创建了一个 fiddle here

我有 table 如下所示。

我的预期输出如下

逻辑:

我必须创建如上所示的报告。逻辑是从起始编号到结束 material 编号重复相同的行。找出差异,如果存在差异,请重复每个 material number.All 的行,其他列值保持不变。

数据格式。

  1. MaterialNo 将只有一个连字符。(varchar 类型)
  2. 连字符前后的字符数可能不同。
  3. 差异可能高达 150。

所以我试过了

WITH cte
AS (
    SELECT Materialno_start,Materialno_end,name,mtype,noofstock
        ,starts.st AS ns,ends.ed AS nd,diff.s AS d,i = 1
        ,n = convert(VARCHAR(30), starts.st)
        ,n.base AS bs
    FROM data
    CROSS APPLY (VALUES (len(Materialno_start))) leng(mn)
    CROSS APPLY (VALUES (charindex('-', Materialno_start)) ) s(hyp)
    CROSS APPLY (VALUES (substring(Materialno_start, s.hyp - leng.mn + 1, leng.mn))) n(base)
    CROSS APPLY (VALUES (substring(Materialno_start, s.hyp + 1, leng.mn)) ) starts(st)
    CROSS APPLY (VALUES (substring(coalesce(Materialno_end, Materialno_start), s.hyp + 1, leng.mn)) ) ends(ed)
    CROSS APPLY (VALUES (convert(INT, ends.ed) - convert(INT, starts.st))) diff(s)

    UNION ALL

    SELECT Materialno_start,Materialno_end,name,mtype,noofstock ,ns,nd,d,i = i + 1
        ,n = convert(VARCHAR(30), n + 1)
        ,bs
    FROM cte
    WHERE i <= d
    )
SELECT Materialno_start
    ,Materialno_end
    ,bs + n AS MaterialNo
    ,Name
    ,mtype
    ,noofstock
FROM cte
ORDER BY 1

它正在为我提供所需的输出。但我不确定它是否有效,因为有这么多 CROSS APPLY 并且我的生产数据可能有大约 70k 行,拆分后可能会增加到 120k 行。我想知道这是否可以通过任何其他方式更有效地完成,或者我可以在此查询中改进什么。我无权访问生产数据或 QA.So 我无法在真实数据中对此进行测试。我得到了 100 行的样本数据,我使用这个查询来实现我的输出。

简单来说,Tally 看起来像这样:

WITH N AS(
    SELECT N
    FROM (VALUES(NULL),(NULL),(NULL),(NULL),(NULL),(NULL),(NULL),(NULL),(NULL),(NULL))N(N)),
Tally AS(
    SELECT TOP (200)
           ROW_NUMBER() OVER (ORDER BY (SELECT NULL)) AS I
    FROM N N1, N N2, N N3)
SELECT *
FROM Tally;

然后我怀疑你想做什么,替换rCTe(和一些Cross适用),会是这样的:

WITH N AS
    (SELECT N
     FROM (VALUES (NULL),
                  (NULL),
                  (NULL),
                  (NULL),
                  (NULL),
                  (NULL),
                  (NULL),
                  (NULL),
                  (NULL),
                  (NULL)) N (N) ),
Tally AS
    (SELECT TOP (200)
            ROW_NUMBER() OVER (ORDER BY (SELECT NULL)) -1 AS I
     FROM N N1,
          N N2,
          N N3),
cte AS
    (SELECT D.Materialno_start,
            D.Materialno_end,
            D.Name,
            D.MType,
            D.Noofstock,
            CONCAT(LEFT(D.Materialno_start,CHARINDEX('-',D.Materialno_start)),V.NoStart + ISNULL(T.I,0)) AS NewID
     FROM dbo.[data] D
          CROSS APPLY (VALUES(TRY_CONVERT(int,STUFF(D.Materialno_start,1,CHARINDEX('-',D.Materialno_start),'')),TRY_CONVERT(int,STUFF(D.Materialno_end,1,CHARINDEX('-',D.Materialno_end),'')))) V(NoStart,NoEnd)       
          LEFT JOIN Tally T ON T.I <= V.NoEnd - V.NoStart)
SELECT Materialno_start,
       Materialno_end,
       Materialno_start AS MaterialNo,
       Name,
       mtype,
       noofstock,
       NewID
FROM cte
ORDER BY cte.Materialno_start;