[英]SQL Server CTE doesn't Join Properly
该项目的数据包含两列,以分号分隔的字符串。 这些实际上是有序对。 因此,例如,在:“ a; b; c”,“ x; y; z”中,“ a”与“ x”配对。 我们的查询目标是创建一个表,在该表中一次清楚地表示这一关系。
这是一个重新创建示例数据的脚本:
DROP TABLE IF EXISTS dbo.sampleData;
DROP TABLE IF EXISTS dbo.lookupCPT;
GO
CREATE TABLE sampleData
(
numRow bigint IDENTITY(1,1) NOT NULL CONSTRAINT PK_numRow PRIMARY KEY,
sDelimQty varchar(MAX) NULL,
sDelimCPT varchar(MAX) NULL
)
CREATE TABLE lookupCPT
(
numRow bigint IDENTITY(1,1) NOT NULL CONSTRAINT PK_numRowCPT PRIMARY KEY,
sCPTCode varchar(10) NULL,
decCPTRate decimal(16,2) NULL
)
INSERT [dbo].[lookupCPT] ([numRow], [sCPTCode], [decCPTRate])
VALUES (1, N'123', CAST(4.00 AS Decimal(16, 2)))
INSERT [dbo].[lookupCPT] ([numRow], [sCPTCode], [decCPTRate])
VALUES (2, N'456', CAST(5.00 AS Decimal(16, 2)))
INSERT [dbo].[lookupCPT] ([numRow], [sCPTCode], [decCPTRate])
VALUES (3, N'789', CAST(7.00 AS Decimal(16, 2)))
INSERT [dbo].[sampleData] ([numRow], [sDelimQty], [sDelimCPT])
VALUES (1, N'1;2', N'123;789')
INSERT [dbo].[sampleData] ([numRow], [sDelimQty], [sDelimCPT])
VALUES (2, N'3', N'456')
我们尝试使用通用表表达式来完成此操作:
WITH Qty_CTE (numRowQ, Qty) AS
(
SELECT numRow, value
FROM sampleData
CROSS APPLY STRING_SPLIT(sDelimQty, ';')
),
CPT_CTE (numRowC, CPT) AS
(
SELECT numRow, value
FROM sampleData
CROSS APPLY STRING_SPLIT(sDelimCPT, ';')
)
SELECT *
FROM sampleData
JOIN CPT_CTE c on c.numRowC = sampleData.numRow
JOIN Qty_CTE q on q.numRowQ = sampleData.numRow
但是,这样做会使输出中的行数加倍:
但是,如果我们删除两个联接之一,它将正确返回:
有任何想法吗? 非常感谢
在提供所有有用的答案之后,下面是最终的解决方案。 干杯!
WITH Qty_CTE (numRowQ, Qty, RN) AS
(
SELECT
numRow, value,
ROW_NUMBER() OVER (ORDER BY (SELECT NULL)) AS RN
FROM
sampleData
CROSS APPLY
STRING_SPLIT(sDelimQty, ';')
),
CPT_CTE (numRowC, CPT, CPTRate, RN) AS
(
SELECT
s.numRow, value as CPT, l.decCPTRate as CPTRate,
ROW_NUMBER() OVER (ORDER BY (SELECT NULL)) AS RN
FROM
sampleData s
CROSS APPLY
STRING_SPLIT(sDelimCPT, ';')
JOIN
lookupCPT l ON value = l.sCPTCode
)
SELECT
numRow, sDelimCPT, sDelimQty, CPT, CPTRate, Qty, CPTRate * Qty as Total
FROM
sampleData
JOIN
CPT_CTE c on c.numRowC = sampleData.numRow
JOIN
Qty_CTE q on q.numRowQ = sampleData.numRow AND c.RN = q.RN
如果您的STRING_SPLIT
函数保留顺序,那么它将起作用。
WITH Qty_CTE (numRowQ, Qty, RN) AS
(
SELECT numRow, value, ROW_NUMBER() OVER (ORDER BY (SELECT NULL)) AS RN
FROM sampleData
CROSS APPLY STRING_SPLIT(sDelimQty, ';')
),
CPT_CTE (numRowC, CPT, RN) AS
(
SELECT numRow, value, ROW_NUMBER() OVER (ORDER BY (SELECT NULL)) AS RN
FROM sampleData
CROSS APPLY STRING_SPLIT(sDelimCPT, ';')
)
SELECT * FROM sampleData
JOIN CPT_CTE c on c.numRowC = sampleData.numRow
JOIN Qty_CTE q on q.numRowQ = sampleData.numRow AND c.RN = q.RN
您的示例q1和q2均按预期工作。 Qty_CTE
的基数为3(记录1出现两次,记录2出现一次), CPT_CTE
也是CPT_CTE
。 sampleData
的基数为2(每行仅出现一次)
由于您正在加入PK, Qty_CTE
CPT_CTE
x Qty_CTE
x CPT_CTE
应该返回5条记录(记录数为1的记录为1x2x2,记录数为2的记录为1x1x1)。 如果删除Qty_CTE
或CPT_CTE
它应该返回3条记录(确实如此)(第2行为1x1x1记录,第1行为1x2记录)。
如果您有一个预期的结果,我们可以提出一个解决方案。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.