【问题标题】:Cross Join followed by Left Join交叉连接后左连接
【发布时间】:2011-03-14 20:07:31
【问题描述】:

是否可以在 2 个表之间进行 CROSS JOIN,然后在第 3 个表上进行 LEFT JOIN,然后再进行更多的左联接?我正在使用 SQL Server 2000/2005。

我正在运行以下查询,这是非常直接的 IMO,但我收到了一个错误。

select  P.PeriodID,
        P.PeriodQuarter,
        P.PeriodYear,
        M.Name,
        M.AuditTypeId,
        A.AuditId
from Period P, Member M

LEFT JOIN Audits A 
ON P.PeriodId = A.PeriodId

WHERE 
    P.PeriodID > 29 AND P.PeriodID < 38
    AND M.AuditTypeId in (1,2,3,4)
order by M.Name

我收到以下错误:

消息 4104,第 16 级,状态 1,第 1 行 多部分标识符“P.PeriodId” 无法绑定。

如果我删除 LEFT JOIN,则查询有效。但是,我需要 LEFT JOIN,因为我需要从其他表中提取更多信息。

我做错了什么?有没有更好的方法?

【问题讨论】:

    标签: sql-server left-join cross-join


    【解决方案1】:

    您不能组合隐式和显式连接 - see this running example

    CROSS JOIN 在系统中应该很少使用,我希望每个人都明确地确保它显然不是编码错误或设计错误。

    如果您想进行隐式左外连接,请执行此操作(SQL Azure 不支持):

    select  P.PeriodID,
            P.PeriodQuarter,
            P.PeriodYear,
            M.Name,
            M.AuditTypeId,
            A.AuditId
    from #Period P, #Member M, #Audits A 
    WHERE 
        P.PeriodID > 29 AND P.PeriodID < 38
        AND M.AuditTypeId in (1,2,3,4)
        AND P.PeriodId *= A.PeriodId
    order by M.Name​
    

    【讨论】:

    • 谢谢。这让我现在更清楚了。进行交叉连接是我能想到的解决我的特定问题的唯一方法。 '*=' 运算符有什么作用呢?
    • @Saajid Imsail *= 是用于隐式连接的旧式 LEFT JOIN 运算符。
    • 该运算符不可靠且已弃用,正确的解决方法是使用显式联接。没有理由不在任何查询中使用显式联接。
    • 可以结合隐式和显式连接,逗号只是比关键字连接的优先级低,并且不被弃用。 *= 样式外连接已弃用。 PS 每个 JOIN ON 都涉及语义上的交叉连接。所以说我们一直在交叉加入是合理的。我们很少交叉连接而不(立即)想要通过 ON 或 WHERE 过滤它。
    【解决方案2】:

    您在查询中忘记了 CROSS JOIN:

    select  P.PeriodID,
            P.PeriodQuarter,
            P.PeriodYear,
            M.Name,
            M.AuditTypeId,
            A.AuditId
    from Period P CROSS JOIN Member M
    
    LEFT JOIN Audits A 
    ON P.PeriodId = A.PeriodId
    
    WHERE 
        P.PeriodID > 29 AND P.PeriodID < 38
        AND M.AuditTypeId in (1,2,3,4)
    order by M.Name
    

    【讨论】:

    • 我不需要指定它,AFAIK。如果我将 LEFT JOIN 删除到 Audits 表中,则查询工作正常。根据我的阅读,我的 OP 定义了一个隐式交叉连接。
    • 好的,所以我尝试了你的代码,现在它可以工作了。但是为什么呢?这没有意义。
    • @Saajid:SQL 倾向于一次查看整个子句。例如你不能说select a+b as c, 2*c as double_c 因为c 在select 子句开始时没有定义。混合新旧样式连接时也会发生同样的事情。 from 子句中逗号之间的部分每个都被查看,就好像并列一样。所以在逗号左侧定义的 P 在右侧看不到。另一个例子见stackoverflow.com/questions/1080097/…
    • 注意:您可以在 from 子句中反转 P & M,但显式交叉连接更好。我们知道其目的是创建一个交叉连接,这不是错误的旧式内部连接。
    猜你喜欢
    • 2022-08-18
    • 1970-01-01
    • 1970-01-01
    • 2017-11-03
    • 2013-02-25
    • 1970-01-01
    • 2011-02-12
    • 2018-09-16
    • 2013-02-04
    相关资源
    最近更新 更多