我已经在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
;
答案 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
语句中对表进行了评估并指定了表的检查条件,并且如果您忘记了语句在何处,则联接将变为Cross
或Cartesian 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子句中转换联接条件。