根据两列的范围重复行
Repeat the rows based on the Range of two columns
我已经为以下数据和我尝试过的查询创建了一个 fiddle here。
我有 table 如下所示。
我的预期输出如下
逻辑:
我必须创建如上所示的报告。逻辑是从起始编号到结束 material 编号重复相同的行。找出差异,如果存在差异,请重复每个 material number.All 的行,其他列值保持不变。
数据格式。
- MaterialNo 将只有一个连字符。(varchar 类型)
- 连字符前后的字符数可能不同。
- 差异可能高达 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;
我已经为以下数据和我尝试过的查询创建了一个 fiddle here。
我有 table 如下所示。
我的预期输出如下
逻辑:
我必须创建如上所示的报告。逻辑是从起始编号到结束 material 编号重复相同的行。找出差异,如果存在差异,请重复每个 material number.All 的行,其他列值保持不变。
数据格式。
- MaterialNo 将只有一个连字符。(varchar 类型)
- 连字符前后的字符数可能不同。
- 差异可能高达 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;