Unpivot 交叉应用问题
Unpivot cross apply issue
我有以下查询,它使用 CROSS APPLY
将三列反透视为一列,我正在使用 ROW_NUMBER()
函数为其分配一个唯一的 VOUCHER_LINE_NUM
。
我面临的问题是,当我有一个 INVOICE_ID
与多个 VOUCHER_LINE_NUM
相关联时,我的非透视行对于每个 VOUCHER_LINE_NUM 都会重复。我只想将 'Freight' 和 'Tax' 行 每个 INVOICE_ID
逆透视一次。这是下面输出的一个示例,它与 INVOICE_ID
1100000721021 重复:
当前输出:
INVOICE_ID VOUCHER_LINE_NUM LineType Value
1100000720667 1 Merchandise 17480.820
1100000720667 2 Freight 59.500
1100000721021 1 Merchandise 82.640
1100000721021 2 Freight 129.010
1100000721021 2 Merchandise 542.120
1100000721021 3 Freight 129.010
1100000721021 3 Merchandise 126.890
1100000721021 4 Freight 129.010
1100000721021 4 Merchandise 1022.030
1100000721021 5 Freight 129.010
1100000721196 5 Merchandise 4680.200
1100000721196 6 Freight 55.500
1100000721196 7 Tax 512.890
在上面的示例中,对于每个与 INVOICE_ID
1100000721021 关联的 VOUCHER_LINE_NUM
,我得到了重复的 'Freight' 行(Value
129.010)。这是 CREATE TABLE
和 INSERT
脚本和当前查询:
CREATE TABLE #TempVOUCHER_LINE (BUSINESS_UNIT varchar(10), VOUCHER_ID varchar(16), VOUCHER_LINE_NUM varchar (4), MERCHANDISE_AMT decimal (8,3))
CREATE TABLE #TempDISTRIB_LINE (BUSINESS_UNIT varchar(10), VOUCHER_ID varchar(16), VOUCHER_LINE_NUM varchar (4))
CREATE TABLE #TempVOUCHER (BUSINESS_UNIT varchar(10), VOUCHER_ID varchar(16), FREIGHT_AMT decimal (7,3), SALETX_AMT decimal (7,3), INVOICE_DT datetime, ACCOUNTING_DT datetime, CLOSE_STATUS varchar(4) )
CREATE TABLE #TempPYMNT_VCHR_XREF (BUSINESS_UNIT varchar(10), VOUCHER_ID varchar(16), PYMNT_ID varchar (10))
INSERT INTO #TempVOUCHER_LINE
(BUSINESS_UNIT, VOUCHER_ID, VOUCHER_LINE_NUM, MERCHANDISE_AMT)
VALUES ('11000', '00720667', '1', 17480.820),
('11000', '00721196', '5', 4680.200),
('11000', '00721021', '1', 82.64),
('11000', '00721021', '2', 542.12),
('11000', '00721021', '3', 126.89),
('11000', '00721021', '4', 1022.03)
INSERT INTO #TempDISTRIB_LINE
(BUSINESS_UNIT, VOUCHER_ID, VOUCHER_LINE_NUM)
VALUES ('11000', '00720667', '1'),
('11000', '00721196', '5'),
('11000', '00721021', '1'),
('11000', '00721021', '2'),
('11000', '00721021', '3'),
('11000', '00721021', '4')
INSERT INTO #TempVOUCHER
(BUSINESS_UNIT, VOUCHER_ID, FREIGHT_AMT, SALETX_AMT, INVOICE_DT, ACCOUNTING_DT, CLOSE_STATUS)
VALUES ('11000', '00720667', 59.50, 0.00, '05-03-2019', '05-14-2014', 'A'),
('11000', '00721196', 55.50, 512.890, '08-10-2020', '08-12-2020', 'A'),
('11000', '00721021', 129.01, 0.00, '12-13-2019', '12-16-2019', 'A')
INSERT INTO #TempPYMNT_VCHR_XREF
(BUSINESS_UNIT, VOUCHER_ID, PYMNT_ID)
VALUES ('11000', '00720667', ''),
('11000', '00721196', ''),
('11000', '00721021', '')
;
WITH CTE AS
(SELECT CONCAT(A.BUSINESS_UNIT, A.VOUCHER_ID) AS INVOICE_ID,
A.VOUCHER_LINE_NUM,
A.MERCHANDISE_AMT,
C.FREIGHT_AMT,
C.SALETX_AMT
FROM #TempVOUCHER_LINE A
LEFT OUTER JOIN #TempDISTRIB_LINE B ON B.BUSINESS_UNIT = A.BUSINESS_UNIT
AND B.VOUCHER_ID = A.VOUCHER_ID
AND B.VOUCHER_LINE_NUM = A.VOUCHER_LINE_NUM
LEFT OUTER JOIN #TempVOUCHER C ON C.BUSINESS_UNIT = A.BUSINESS_UNIT
AND C.VOUCHER_ID = A.VOUCHER_ID
LEFT OUTER JOIN #TempPYMNT_VCHR_XREF I ON I.BUSINESS_UNIT = A.BUSINESS_UNIT
AND I.VOUCHER_ID = A.VOUCHER_ID
WHERE C.INVOICE_DT > '01-03-2019'
AND C.ACCOUNTING_DT < '06-01-2021'
AND I.PYMNT_ID = ''
AND C.CLOSE_STATUS <> 'C'
AND A.VOUCHER_ID IN ('00720667', '00721196', '00721021', '00721171', '00326705'))
SELECT C.INVOICE_ID,
C.VOUCHER_LINE_NUM + ROW_NUMBER() OVER (PARTITION BY C.INVOICE_ID, VOUCHER_LINE_NUM ORDER BY VOUCHER_LINE_NUM) - 1 AS VOUCHER_LINE_NUM,
V.LineType,
V.[Value]
FROM CTE C
CROSS APPLY (VALUES('Merchandise',C.MERCHANDISE_AMT),
('Freight',C.FREIGHT_AMT),
('Tax',C.SALETX_AMT))V (LineType, Value)
WHERE V.[Value] <> 0;
期望输出:
INVOICE_ID VOUCHER_LINE_NUM LineType Value
1100000720667 1 Merchandise 17480.820
1100000720667 2 Freight 59.500
1100000721021 1 Merchandise 82.640
1100000721021 2 Merchandise 542.120
1100000721021 3 Merchandise 126.890
1100000721021 4 Merchandise 1022.030
1100000721021 5 Freight 129.010
1100000721196 5 Merchandise 4680.200
1100000721196 6 Freight 55.500
1100000721196 7 Tax 512.890
在上面的期望输出中,运费线仅在每个 INVOICE_ID
出现 一次 并分配给最高(最大值)VOUCHER_LINE_NUM
对于 INVOICE_ID + 1
,因此此 INVOICE_ID
(1100000721021) 的 VOUCHER_LINE_NUM
为 1,2,3,4,因此运费(and/or 税)分配给 VOUCHER_LINE_NUM
5(和 6,如果它也有 Tax <> 0)。
编辑 - 与建议的答案重复:
当 FREIGHT_AMT
的值与您的 CTE 无关时,您需要将其更改为 0.00
。您可以使用 CASE
表达式和 ROW_NUMBER
:
WITH CTE AS
(SELECT CONCAT(A.BUSINESS_UNIT, A.VOUCHER_ID) AS INVOICE_ID,
A.VOUCHER_LINE_NUM,
A.MERCHANDISE_AMT,
CASE WHEN ROW_NUMBER() OVER (PARTITION BY CONCAT(A.BUSINESS_UNIT, A.VOUCHER_ID) ORDER BY C.FREIGHT_AMT DESC, A.VOUCHER_LINE_NUM ASC) = 1 THEN C.FREIGHT_AMT ELSE 0.00 END AS FREIGHT_AMT,
C.SALETX_AMT
FROM #TempVOUCHER_LINE A --"A" is for VOUCHER_LINE? What A?
LEFT OUTER JOIN #TempDISTRIB_LINE B ON B.BUSINESS_UNIT = A.BUSINESS_UNIT --"B" is for DISTRIB_LINE. I would say "D" is.
AND B.VOUCHER_ID = A.VOUCHER_ID
AND B.VOUCHER_LINE_NUM = A.VOUCHER_LINE_NUM
INNER JOIN #TempVOUCHER C ON C.BUSINESS_UNIT = A.BUSINESS_UNIT --"C" is for Voucher? I would say "V" is
AND C.VOUCHER_ID = A.VOUCHER_ID
INNER JOIN #TempPYMNT_VCHR_XREF I ON I.BUSINESS_UNIT = A.BUSINESS_UNIT --"I" is for PYMNT_VCHR_XREF? What I?
AND I.VOUCHER_ID = A.VOUCHER_ID
WHERE C.INVOICE_DT > '20190103'
AND C.ACCOUNTING_DT < '20210601'
AND I.PYMNT_ID = ''
AND C.CLOSE_STATUS <> 'C'
AND A.VOUCHER_ID IN ('00720667', '00721196', '00721021', '00721171', '00326705'))
SELECT C.INVOICE_ID,
MIN(C.VOUCHER_LINE_NUM) OVER (PARTITION BY C.INVOICE_ID) + ROW_NUMBER() OVER (PARTITION BY C.INVOICE_ID ORDER BY VOUCHER_LINE_NUM) - 1 AS VOUCHER_LINE_NUM,
V.LineType,
V.[Value]
FROM CTE C
CROSS APPLY (VALUES('Merchandise',C.MERCHANDISE_AMT),
('Freight',C.FREIGHT_AMT),
('Tax',C.SALETX_AMT))V (LineType, Value)
WHERE V.[Value] <> 0;
此外,我真的建议修复您的别名。 DISTRIB_LINE
的“A”没有什么意义(它里面没有任何 A)而且我不会使用字母“C”来定义名称 VOUCHER
(“V”会很远更合适)。
我还更改了您的一些 JOIN
。当它们的几个列的值不能是 NULL
时,LEFT OUTER JOIN
到 #TempVOUCHER
和 #TempPYMNT_VCHR_XREF
是没有意义的。当行不存在时,列不可能有非 NULL
值。
最后,我不明白为什么 table #TempDISTRIB_LINE
甚至在查询中,它没有在 WHERE
、ON
或SELECT
作为 LEFT OUTER JOIN
它甚至不做任何过滤数据的事情。它可以做的“最好”是在一对多关系中导致重复行。 table 应该从查询中删除。
我有以下查询,它使用 CROSS APPLY
将三列反透视为一列,我正在使用 ROW_NUMBER()
函数为其分配一个唯一的 VOUCHER_LINE_NUM
。
我面临的问题是,当我有一个 INVOICE_ID
与多个 VOUCHER_LINE_NUM
相关联时,我的非透视行对于每个 VOUCHER_LINE_NUM 都会重复。我只想将 'Freight' 和 'Tax' 行 每个 INVOICE_ID
逆透视一次。这是下面输出的一个示例,它与 INVOICE_ID
1100000721021 重复:
当前输出:
INVOICE_ID VOUCHER_LINE_NUM LineType Value
1100000720667 1 Merchandise 17480.820
1100000720667 2 Freight 59.500
1100000721021 1 Merchandise 82.640
1100000721021 2 Freight 129.010
1100000721021 2 Merchandise 542.120
1100000721021 3 Freight 129.010
1100000721021 3 Merchandise 126.890
1100000721021 4 Freight 129.010
1100000721021 4 Merchandise 1022.030
1100000721021 5 Freight 129.010
1100000721196 5 Merchandise 4680.200
1100000721196 6 Freight 55.500
1100000721196 7 Tax 512.890
在上面的示例中,对于每个与 INVOICE_ID
1100000721021 关联的 VOUCHER_LINE_NUM
,我得到了重复的 'Freight' 行(Value
129.010)。这是 CREATE TABLE
和 INSERT
脚本和当前查询:
CREATE TABLE #TempVOUCHER_LINE (BUSINESS_UNIT varchar(10), VOUCHER_ID varchar(16), VOUCHER_LINE_NUM varchar (4), MERCHANDISE_AMT decimal (8,3))
CREATE TABLE #TempDISTRIB_LINE (BUSINESS_UNIT varchar(10), VOUCHER_ID varchar(16), VOUCHER_LINE_NUM varchar (4))
CREATE TABLE #TempVOUCHER (BUSINESS_UNIT varchar(10), VOUCHER_ID varchar(16), FREIGHT_AMT decimal (7,3), SALETX_AMT decimal (7,3), INVOICE_DT datetime, ACCOUNTING_DT datetime, CLOSE_STATUS varchar(4) )
CREATE TABLE #TempPYMNT_VCHR_XREF (BUSINESS_UNIT varchar(10), VOUCHER_ID varchar(16), PYMNT_ID varchar (10))
INSERT INTO #TempVOUCHER_LINE
(BUSINESS_UNIT, VOUCHER_ID, VOUCHER_LINE_NUM, MERCHANDISE_AMT)
VALUES ('11000', '00720667', '1', 17480.820),
('11000', '00721196', '5', 4680.200),
('11000', '00721021', '1', 82.64),
('11000', '00721021', '2', 542.12),
('11000', '00721021', '3', 126.89),
('11000', '00721021', '4', 1022.03)
INSERT INTO #TempDISTRIB_LINE
(BUSINESS_UNIT, VOUCHER_ID, VOUCHER_LINE_NUM)
VALUES ('11000', '00720667', '1'),
('11000', '00721196', '5'),
('11000', '00721021', '1'),
('11000', '00721021', '2'),
('11000', '00721021', '3'),
('11000', '00721021', '4')
INSERT INTO #TempVOUCHER
(BUSINESS_UNIT, VOUCHER_ID, FREIGHT_AMT, SALETX_AMT, INVOICE_DT, ACCOUNTING_DT, CLOSE_STATUS)
VALUES ('11000', '00720667', 59.50, 0.00, '05-03-2019', '05-14-2014', 'A'),
('11000', '00721196', 55.50, 512.890, '08-10-2020', '08-12-2020', 'A'),
('11000', '00721021', 129.01, 0.00, '12-13-2019', '12-16-2019', 'A')
INSERT INTO #TempPYMNT_VCHR_XREF
(BUSINESS_UNIT, VOUCHER_ID, PYMNT_ID)
VALUES ('11000', '00720667', ''),
('11000', '00721196', ''),
('11000', '00721021', '')
;
WITH CTE AS
(SELECT CONCAT(A.BUSINESS_UNIT, A.VOUCHER_ID) AS INVOICE_ID,
A.VOUCHER_LINE_NUM,
A.MERCHANDISE_AMT,
C.FREIGHT_AMT,
C.SALETX_AMT
FROM #TempVOUCHER_LINE A
LEFT OUTER JOIN #TempDISTRIB_LINE B ON B.BUSINESS_UNIT = A.BUSINESS_UNIT
AND B.VOUCHER_ID = A.VOUCHER_ID
AND B.VOUCHER_LINE_NUM = A.VOUCHER_LINE_NUM
LEFT OUTER JOIN #TempVOUCHER C ON C.BUSINESS_UNIT = A.BUSINESS_UNIT
AND C.VOUCHER_ID = A.VOUCHER_ID
LEFT OUTER JOIN #TempPYMNT_VCHR_XREF I ON I.BUSINESS_UNIT = A.BUSINESS_UNIT
AND I.VOUCHER_ID = A.VOUCHER_ID
WHERE C.INVOICE_DT > '01-03-2019'
AND C.ACCOUNTING_DT < '06-01-2021'
AND I.PYMNT_ID = ''
AND C.CLOSE_STATUS <> 'C'
AND A.VOUCHER_ID IN ('00720667', '00721196', '00721021', '00721171', '00326705'))
SELECT C.INVOICE_ID,
C.VOUCHER_LINE_NUM + ROW_NUMBER() OVER (PARTITION BY C.INVOICE_ID, VOUCHER_LINE_NUM ORDER BY VOUCHER_LINE_NUM) - 1 AS VOUCHER_LINE_NUM,
V.LineType,
V.[Value]
FROM CTE C
CROSS APPLY (VALUES('Merchandise',C.MERCHANDISE_AMT),
('Freight',C.FREIGHT_AMT),
('Tax',C.SALETX_AMT))V (LineType, Value)
WHERE V.[Value] <> 0;
期望输出:
INVOICE_ID VOUCHER_LINE_NUM LineType Value
1100000720667 1 Merchandise 17480.820
1100000720667 2 Freight 59.500
1100000721021 1 Merchandise 82.640
1100000721021 2 Merchandise 542.120
1100000721021 3 Merchandise 126.890
1100000721021 4 Merchandise 1022.030
1100000721021 5 Freight 129.010
1100000721196 5 Merchandise 4680.200
1100000721196 6 Freight 55.500
1100000721196 7 Tax 512.890
在上面的期望输出中,运费线仅在每个 INVOICE_ID
出现 一次 并分配给最高(最大值)VOUCHER_LINE_NUM
对于 INVOICE_ID + 1
,因此此 INVOICE_ID
(1100000721021) 的 VOUCHER_LINE_NUM
为 1,2,3,4,因此运费(and/or 税)分配给 VOUCHER_LINE_NUM
5(和 6,如果它也有 Tax <> 0)。
编辑 - 与建议的答案重复:
当 FREIGHT_AMT
的值与您的 CTE 无关时,您需要将其更改为 0.00
。您可以使用 CASE
表达式和 ROW_NUMBER
:
WITH CTE AS
(SELECT CONCAT(A.BUSINESS_UNIT, A.VOUCHER_ID) AS INVOICE_ID,
A.VOUCHER_LINE_NUM,
A.MERCHANDISE_AMT,
CASE WHEN ROW_NUMBER() OVER (PARTITION BY CONCAT(A.BUSINESS_UNIT, A.VOUCHER_ID) ORDER BY C.FREIGHT_AMT DESC, A.VOUCHER_LINE_NUM ASC) = 1 THEN C.FREIGHT_AMT ELSE 0.00 END AS FREIGHT_AMT,
C.SALETX_AMT
FROM #TempVOUCHER_LINE A --"A" is for VOUCHER_LINE? What A?
LEFT OUTER JOIN #TempDISTRIB_LINE B ON B.BUSINESS_UNIT = A.BUSINESS_UNIT --"B" is for DISTRIB_LINE. I would say "D" is.
AND B.VOUCHER_ID = A.VOUCHER_ID
AND B.VOUCHER_LINE_NUM = A.VOUCHER_LINE_NUM
INNER JOIN #TempVOUCHER C ON C.BUSINESS_UNIT = A.BUSINESS_UNIT --"C" is for Voucher? I would say "V" is
AND C.VOUCHER_ID = A.VOUCHER_ID
INNER JOIN #TempPYMNT_VCHR_XREF I ON I.BUSINESS_UNIT = A.BUSINESS_UNIT --"I" is for PYMNT_VCHR_XREF? What I?
AND I.VOUCHER_ID = A.VOUCHER_ID
WHERE C.INVOICE_DT > '20190103'
AND C.ACCOUNTING_DT < '20210601'
AND I.PYMNT_ID = ''
AND C.CLOSE_STATUS <> 'C'
AND A.VOUCHER_ID IN ('00720667', '00721196', '00721021', '00721171', '00326705'))
SELECT C.INVOICE_ID,
MIN(C.VOUCHER_LINE_NUM) OVER (PARTITION BY C.INVOICE_ID) + ROW_NUMBER() OVER (PARTITION BY C.INVOICE_ID ORDER BY VOUCHER_LINE_NUM) - 1 AS VOUCHER_LINE_NUM,
V.LineType,
V.[Value]
FROM CTE C
CROSS APPLY (VALUES('Merchandise',C.MERCHANDISE_AMT),
('Freight',C.FREIGHT_AMT),
('Tax',C.SALETX_AMT))V (LineType, Value)
WHERE V.[Value] <> 0;
此外,我真的建议修复您的别名。 DISTRIB_LINE
的“A”没有什么意义(它里面没有任何 A)而且我不会使用字母“C”来定义名称 VOUCHER
(“V”会很远更合适)。
我还更改了您的一些 JOIN
。当它们的几个列的值不能是 NULL
时,LEFT OUTER JOIN
到 #TempVOUCHER
和 #TempPYMNT_VCHR_XREF
是没有意义的。当行不存在时,列不可能有非 NULL
值。
最后,我不明白为什么 table #TempDISTRIB_LINE
甚至在查询中,它没有在 WHERE
、ON
或SELECT
作为 LEFT OUTER JOIN
它甚至不做任何过滤数据的事情。它可以做的“最好”是在一对多关系中导致重复行。 table 应该从查询中删除。