繁体   English   中英

SQL Server:加入新语法(ANSI与非ANSI SQL JOIN语法)

[英]SQL Server : joins new syntax(ANSI vs. non-ANSI SQL JOIN syntax)

我试图将旧的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

转换后的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

发现

原始SQL和修改后的SQL的结果相同(最多3个表的连接),但是将第四个表(TableD)连接到修改的SQL时,返回的行数不同。

使用SQL Server(不建议使用)专有ANSI 89连接语法*==*时,谓词中字段的顺序很重要=*

所以当

SELECT  *
FROM    TableA AS A
        LEFT JOIN TableB AS B
            ON A.ColA = B.ColB;

完全一样

SELECT  *
FROM    TableA AS A
        LEFT JOIN TableB AS B
            ON B.ColB = A.ColA;     -- NOTE ORDER HERE

等效

SELECT  *
FROM    TableA AS A, TableB AS b
WHERE   A.ColA *= B.ColB;

与...不同

SELECT  *
FROM    TableA AS A, TableB AS b
WHERE   B.ColA *= A.ColB;

最后一个查询的ANSI 92等效项为

SELECT  *
FROM    TableA AS A
        RIGHT JOIN TableB AS B
            ON A.ColA = B.ColB;

或者,如果您像我一样不喜欢RIGHT JOIN ,那么您可能会写:

SELECT  *
FROM    TableB AS B
        LEFT OUTER JOIN TableA AS A
            ON B.ColB = A.ColA;

因此,实际上,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;

这是等效的重写,并解释了行数的差异

工作实例

需要在兼容级别为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;

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM