我试图将旧的MS sql连接语法转换为新的连接语法,但结果中的行数不匹配.
原始SQL:
select
b.Amount
from
TableA a, TableB b,TableC c, TableD d
where
a.inv_no *= b.inv_no and
a.inv_item *= b.inv_item and
c.currency *= b.cash_ccy and
d.tx_code *= b.cash_receipt
Run Code Online (Sandbox Code Playgroud)
转换的SQL:
SELECT
b.AMOUNT
FROM
(TableA AS a
LEFT OUTER JOIN
TableB AS b ON a.INV_NO = b.INV_NO
AND a.inv_item = b.inv_item
LEFT OUTER JOIN
TableC AS c ON c.currency = b.cash_ccy)
LEFT OUTER JOIN
TableD as d ON d.tx_code = b.cash_receipt
Run Code Online (Sandbox Code Playgroud)
发现
原始SQL和修改后的SQL上的结果在连接3个表时相同,但在将第四个表(TableD)连接到修改后的SQL时,返回的行数不同.
使用SQL Server(已弃用)专有的ANSI 89连接语法*=或时,谓词中字段的顺序很重要=*
所以虽然
SELECT *
FROM TableA AS A
LEFT JOIN TableB AS B
ON A.ColA = B.ColB;
Run Code Online (Sandbox Code Playgroud)
完全一样
SELECT *
FROM TableA AS A
LEFT JOIN TableB AS B
ON B.ColB = A.ColA; -- NOTE ORDER HERE
Run Code Online (Sandbox Code Playgroud)
等价的
SELECT *
FROM TableA AS A, TableB AS b
WHERE A.ColA *= B.ColB;
Run Code Online (Sandbox Code Playgroud)
是不一样的
SELECT *
FROM TableA AS A, TableB AS b
WHERE B.ColA *= A.ColB;
Run Code Online (Sandbox Code Playgroud)
最后一个查询的ANSI 92等价物将是
SELECT *
FROM TableA AS A
RIGHT JOIN TableB AS B
ON A.ColA = B.ColB;
Run Code Online (Sandbox Code Playgroud)
或者,如果你不喜欢RIGHT JOIN我,你可能会写:
SELECT *
FROM TableB AS B
LEFT OUTER JOIN TableA AS A
ON B.ColB = A.ColA;
Run Code Online (Sandbox Code Playgroud)
实际上,ANSI 92连接语法中的等效查询将涉及从TableA,TableC和TableD开始(因为这些是原始WHERE子句中的前导字段).然后由于三者之间没有直接联系,你最终会得到一个交叉联接
SELECT b.Amount
FROM TableA AS a
CROSS JOIN TableD AS d
CROSS JOIN TableC AS c
LEFT JOIN TableB AS B
ON c.currency = b.cash_ccy
AND d.tx_code = b.cash_receipt
AND a.INV_NO = b.INV_NO
AND a.inv_item = b.inv_item;
Run Code Online (Sandbox Code Playgroud)
这是等效的重写,并解释了行数的差异
工作实例
需要在兼容级别为80或更低的SQL Server 2008或更早版本上运行
-- SAMPLE DATA --
CREATE TABLE #TableA (Inv_No INT, Inv_item INT);
CREATE TABLE #TableB (Inv_No INT, Inv_item INT, cash_ccy INT, cash_receipt INT, Amount INT);
CREATE TABLE #TableC (currency INT);
CREATE TABLE #TableD (tx_code INT);
INSERT #TableA (inv_no, inv_item) VALUES (1, 1), (2, 2);
INSERT #TableB (inv_no, inv_item, cash_ccy, cash_receipt, Amount) VALUES (1, 1, 1, 1, 1), (2, 2, 2, 2, 2);
INSERT #TableC (currency) VALUES (1), (2), (3), (4);
INSERT #TableD (tx_code) VALUES (1), (2), (3), (4);
-- ORIGINAL QUERY(32 ROWS)
SELECT
b.Amount
FROM
#TableA a, #TableB b,#TableC c, #TableD d
WHERE
a.inv_no *= b.inv_no and
a.inv_item *= b.inv_item and
c.currency *= b.cash_ccy and
d.tx_code *= b.cash_receipt
-- INCORRECT ANSI 92 REWRITE (2 ROWS)
SELECT b.AMOUNT
FROM #TableA AS a
LEFT OUTER JOIN #TableB AS b
ON a.INV_NO = b.INV_NO
and a.inv_item = b.inv_item
LEFT OUTER JOIN #TableC AS c
ON c.currency = b.cash_ccy
LEFT OUTER JOIN #TableD as d
ON d.tx_code = b.cash_receipt;
-- CORRECT ANSI 92 REWRITE (32 ROWS)
SELECT b.Amount
FROM #TableA AS a
CROSS JOIN #TableD AS d
CROSS JOIN #TableC AS c
LEFT JOIN #TableB AS B
ON c.currency = b.cash_ccy
AND d.tx_code = b.cash_receipt
AND a.INV_NO = b.INV_NO
AND a.inv_item = b.inv_item;
Run Code Online (Sandbox Code Playgroud)