在cte中使用交叉连接与多个变量
Using cross join with multiple variable in cte
我有一些订单号,想检查是否有任何号码被跳过。我将使用左 table 方法,即:
select * from
#CreatedCrossTable (which has all possibilities)
Left Join #MainTableWhichHaveRealSerialNo mt
where
mt is null
没有结构的订单是:“CodeType.Year.Month.SerialNo”。例如:“DP.21.07.001”、“DP.21.07.002”.. 或不是 DP,而是“FB.21.07.001”、“FB.21.07.002”等
我想创建一个交叉 table 模式来确定跳过的 SerilNo 值 (CreatedCrossTable
以上):
(序列号每月重置)
CodeType | Year | Month | SerialNo
DP 21 1 1
DP 21 1 2
DP 21 1 3
DP 21 1 4
...
(All SerialNos must increase max serial number of the original table's SerialNo (MainTableWhichHaveRealSerialNo) Also codeType,year and month values must match)
DP 21 2 1
DP 21 2 2
...
FB 21 1 1
FB 21 1 2
...
FB 21 1 1
FB 21 1 2
FB 21 1 3
...
每个代码和月份的序列号都有不同的最大数量
用于创建 CrossTable。我写了那个代码:
;WITH cteSerialNo AS
(
SELECT 1 AS ORDERNO
UNION ALL
SELECT (ORDERNO+1) AS ORDERNO FROM cteSerialNo WHERE ORDERNO < MAX_ORDER_NO
)
,cteMonthYear AS
(
SELECT CAST('2021.01.01' AS DATE) AS Dt
UNION ALL
SELECT DATEADD(MONTH , 1, Dt) AS Dt
FROM cteMonthYear
WHERE DATEADD (MONTH, 1, Dt) < GETDATE()
)
SELECT
*
FROM
(
SELECT
CODES.CODETYPE,
YEAR(Dts.Dt) AS 'YEAR',
MONTH(Dts.Dt) AS 'MONTH'
FROM
##KK_TBL_CODETYPES AS CODES
CROSS JOIN cteMonthYear AS Dts
) AS CROSSTABLE
CROSS JOIN cteSerialNo AS cSN
如何为这段代码中的每个变量输入 (MAX_ORDER_NO)?
假设最大 SerialNo
值基于 SerialNo
列中的现有值,您可能只想找到该 SerialNo
值之前的所有可能组合,然后删除源数据中匹配的那些:
-- Define test data
declare @t table(CodeType varchar(2),[Year] int,[Month] int,SerialNo int);
insert into @t values
('DP',21,1,1)
,('DP',21,1,2)
,('DP',21,1,3)
--,('DP',21,1,4) -- Missing so should be in Output
,('DP',21,1,5)
,('DP',21,2,1)
,('DP',21,2,2)
,('FB',21,1,1)
,('FB',21,1,2)
,('FB',21,2,1)
,('FB',21,2,2)
--,('FB',21,2,3) -- Missing so should be in Output
,('FB',21,2,4)
;
with m as -- Get Max SerialNo for each grouping
(
select CodeType
,[Year]
,[Month]
,max(SerialNo) as MaxSerialNo
from @t
group by CodeType
,[Year]
,[Month]
)
,t as -- Create a table with 10 rows in
(
select t
from(values(1),(1),(1),(1),(1),(1),(1),(1),(1),(1)) as t(t)
)
,n as -- Self join those 10 rows 5 times to generate a possible 10*10*10*10*10 = 100,000 incrementing numbers using row_number
(
select top(select max(MaxSerialNo) from m) row_number() over (order by (select null)) as n
from t,t t2,t t3,t t4,t t5
)
-- Join from the numbers table to the source data to generate all possible SerialNo values up to the Max
select m.CodeType
,m.[Year]
,m.[Month]
,n.n as SerialNo
from n
left join m
on n.n <= m.MaxSerialNo
except -- Then exclude any that are in the source data
select CodeType
,[Year]
,[Month]
,SerialNo
from @t
order by CodeType
,[Year]
,[Month]
,SerialNo
输出
CodeType
Year
Month
SerialNo
DP
21
1
4
FB
21
2
3
我有一些订单号,想检查是否有任何号码被跳过。我将使用左 table 方法,即:
select * from
#CreatedCrossTable (which has all possibilities)
Left Join #MainTableWhichHaveRealSerialNo mt
where
mt is null
没有结构的订单是:“CodeType.Year.Month.SerialNo”。例如:“DP.21.07.001”、“DP.21.07.002”.. 或不是 DP,而是“FB.21.07.001”、“FB.21.07.002”等
我想创建一个交叉 table 模式来确定跳过的 SerilNo 值 (CreatedCrossTable 以上):
(序列号每月重置)
CodeType | Year | Month | SerialNo
DP 21 1 1
DP 21 1 2
DP 21 1 3
DP 21 1 4
...
(All SerialNos must increase max serial number of the original table's SerialNo (MainTableWhichHaveRealSerialNo) Also codeType,year and month values must match)
DP 21 2 1
DP 21 2 2
...
FB 21 1 1
FB 21 1 2
...
FB 21 1 1
FB 21 1 2
FB 21 1 3
...
每个代码和月份的序列号都有不同的最大数量 用于创建 CrossTable。我写了那个代码:
;WITH cteSerialNo AS
(
SELECT 1 AS ORDERNO
UNION ALL
SELECT (ORDERNO+1) AS ORDERNO FROM cteSerialNo WHERE ORDERNO < MAX_ORDER_NO
)
,cteMonthYear AS
(
SELECT CAST('2021.01.01' AS DATE) AS Dt
UNION ALL
SELECT DATEADD(MONTH , 1, Dt) AS Dt
FROM cteMonthYear
WHERE DATEADD (MONTH, 1, Dt) < GETDATE()
)
SELECT
*
FROM
(
SELECT
CODES.CODETYPE,
YEAR(Dts.Dt) AS 'YEAR',
MONTH(Dts.Dt) AS 'MONTH'
FROM
##KK_TBL_CODETYPES AS CODES
CROSS JOIN cteMonthYear AS Dts
) AS CROSSTABLE
CROSS JOIN cteSerialNo AS cSN
如何为这段代码中的每个变量输入 (MAX_ORDER_NO)?
假设最大 SerialNo
值基于 SerialNo
列中的现有值,您可能只想找到该 SerialNo
值之前的所有可能组合,然后删除源数据中匹配的那些:
-- Define test data
declare @t table(CodeType varchar(2),[Year] int,[Month] int,SerialNo int);
insert into @t values
('DP',21,1,1)
,('DP',21,1,2)
,('DP',21,1,3)
--,('DP',21,1,4) -- Missing so should be in Output
,('DP',21,1,5)
,('DP',21,2,1)
,('DP',21,2,2)
,('FB',21,1,1)
,('FB',21,1,2)
,('FB',21,2,1)
,('FB',21,2,2)
--,('FB',21,2,3) -- Missing so should be in Output
,('FB',21,2,4)
;
with m as -- Get Max SerialNo for each grouping
(
select CodeType
,[Year]
,[Month]
,max(SerialNo) as MaxSerialNo
from @t
group by CodeType
,[Year]
,[Month]
)
,t as -- Create a table with 10 rows in
(
select t
from(values(1),(1),(1),(1),(1),(1),(1),(1),(1),(1)) as t(t)
)
,n as -- Self join those 10 rows 5 times to generate a possible 10*10*10*10*10 = 100,000 incrementing numbers using row_number
(
select top(select max(MaxSerialNo) from m) row_number() over (order by (select null)) as n
from t,t t2,t t3,t t4,t t5
)
-- Join from the numbers table to the source data to generate all possible SerialNo values up to the Max
select m.CodeType
,m.[Year]
,m.[Month]
,n.n as SerialNo
from n
left join m
on n.n <= m.MaxSerialNo
except -- Then exclude any that are in the source data
select CodeType
,[Year]
,[Month]
,SerialNo
from @t
order by CodeType
,[Year]
,[Month]
,SerialNo
输出
CodeType | Year | Month | SerialNo |
---|---|---|---|
DP | 21 | 1 | 4 |
FB | 21 | 2 | 3 |