连接三个表,错误,无法绑定多部分标识符“ p.productid”

时间:2018-10-30 07:35:32

标签: sql sql-server

我已经在Northwind数据库上尝试了以下问题:需要知道我在哪里出错。就像我使用where语句一样。

q。列出所有产品从1997年开始的总销售额? 按产品ID,产品名称和1997年的年销售额列出查询结果 按年销售额按降序排序(年销售额是计算列)。 * /

 select p.productid, p.productname , 
            '$'+ CONVERT(varchar(12), sum(od.unitprice*od.quantity*1-od.discount)) as AnnualSales
    from products as p , [Order Details] as od , orders as o
        inner join [Order Details]
    on  p.productid = od.productid
        inner join orders
        on od.orderid = o.orderID
        and o.OrderDate >=  '1997/01/01' and  o.orderdate <= '1997/12/31'
    group by p.productid, p.productname
    order by annualsales desc
    ;

我遇到了这些错误:

        Msg 4104, Level 16, State 1, Line 207
        The multi-part identifier "p.productid" could not be bound.
        Msg 4104, Level 16, State 1, Line 207
        The multi-part identifier "od.productid" could not be bound.
        Msg 4104, Level 16, State 1, Line 209
        The multi-part identifier "od.orderid" could not be bound.

当我这样尝试时,它起作用了,请告知我做错了什么地方:

select p.productid, p.productname , '$'+ CONVERT(varchar(12), sum     (od.unitprice*od.quantity*1-od.discount)) as AnnualSales
from products as p , orders as o , [Order Details] as od
where  p.productid = od.productID
    and o.OrderID = od.OrderID
    and  o.OrderDate >=  '1997/01/01' and  o.orderdate <= '1997/12/31'
group by p.productid, p.productname
order by annualsales desc
;

3 个答案:

答案 0 :(得分:1)

您必须删除在from [Order Details]后用od表示的多余表名,在o上用订单,我认为它将在o.OrderDate >='1997/01/01' and o.orderdate <='1997/12/31'的条件下出现

select p.productid, p.productname , 
            '$'+ CONVERT(varchar(12), sum(od.unitprice*od.quantity*1-od.discount)) as AnnualSales
    from products as p   
        inner join [Order Details] od
      on  p.productid = od.productid
        inner join orders o
        on od.orderid = o.orderID
        where 
        o.OrderDate >='1997/01/01' and o.orderdate <='1997/12/31'
    group by p.productid, p.productname

    ;

答案 1 :(得分:0)

首先不要使用Implicit Join

对于error,您将Implicit Join与逗号连接混合在一起,而Explicit Join使用Join语句。为什么不必须Implicit Join呢?因为在您的where语句中对表进行了评估并指定了表的检查条件,并且如果您忘记了语句在何处,则联接将变为CrossCartesian Product。那将使您的结果混乱。

 select 
      p.productid, p.productname, 
      '$'+ CONVERT(varchar(12), 
      sum(od.unitprice*od.quantity*1-od.discount)) as AnnualSales
 from 
      products as p 
        inner join [Order Details] on  p.productid = od.productid
        inner join orders as o on od.orderid = o.orderID
                             and o.OrderDate >= '1997/01/01' 
                             and o.orderdate <= '1997/12/31'
  group by 
       p.productid, p.productname;

您可以在此处详细了解为什么不可以Implicit Join Bad habits to kick : using old-style JOINs

注意:我只想阐述更多信息,因为操作员会询问错误。

答案 2 :(得分:0)

我认为您已经获得了答案和很好的解释。让我进一步说明“隐式”和“显式”联接的区别。

隐式加入     “隐式连接表示法”仅使用逗号分隔列出要连接的表(在SELECT语句的FROM子句中)。因此,它指定了交叉连接,并且WHERE子句可以应用其他过滤谓词:

这称为 ANSI SQL-89 连接语法。

例如:-

选择* 从员工,部门 WHERE employee.DepartmentID = department.DepartmentID;

显式加入

这称为 SQL-92 联接。 例如:-

选择* 来自员工INNER JOIN部门 ON employee.DepartmentID = department.DepartmentID

这两种语法仍然是最新ANSI SQL标准的一部分,无论从性能还是资源上都没有区别。尊重标准Microsoft并没有计划在不久的将来删除对SQL 89语法的支持。

但是,许多专家更喜欢使用ANSI SQL 92语法编写FROM FROM子句中的SQL Joins,因为它比较容易混淆,因为如果您在where子句中省略或忘记了联接条件,那么

SELECT *
FROM employee, department
--WHERE employee.DepartmentID = department.DepartmentID;

基本上,您将进行交叉联接,但是,如果您忘记在FROM中写ON子句,则会抛出错误。

有关更多详细信息->阅读Itzik Ben-Gan撰写的T-SQL基础知识:第3章有关于该主题的整段内容。

如果您认为WHERE子句是在FROM子句之后求值的,那么SQL 89 synax可能会更慢?不,SQL Server中有一个叫做查询优化器的东西,它非常聪明,并且能够在评估查询之前在where子句中转换联接条件。