我正在尝试回答这个问题:(常规SQL语法)
撰写查询以显示属于纽约市的销售员的所有订单
推销员
salesman_id name city commission
----------- ---------- ---------- ----------
5001 James Hoog New York 0.15
5002 Nail Knite Paris 0.13
5005 Pit Alex London 0.11
5006 Mc Lyon Paris 0.14
5003 Lauson Hen San Jose 0.12
5007 Paul Adam Rome 0.13
订单:
ord_no purch_amt ord_date customer_id salesman_id
---------- ---------- ---------- ----------- -----------
70001 150.5 2012-10-05 3005 5002
70009 270.65 2012-09-10 3001 5005
70002 65.26 2012-10-05 3002 5001
70004 110.5 2012-08-17 3009 5003
70007 948.5 2012-09-10 3005 5002
70005 2400.6 2012-07-27 3007 5001
70008 5760 2012-09-10 3002 5001
70010 1983.43 2012-10-10 3004 5006
70003 2480.4 2012-10-10 3009 5003
70012 250.45 2012-06-27 3008 5002
70011 75.29 2012-08-17 3003 5007
70013 3045.6 2012-04-25 3002 5001
提供的解决方案是使用SubQuery:
select * from orders where salesman_id=
(select salesman_id from salesman
where city='New York')
我知道在SQL中有几个问题的答案,但任何更有效或任何理由使用其中一个?下面的答案带来了相同的结果,所以我想知道为什么使用子查询有什么理由?
select * from orders, salesman
where orders.salesman_id = salesman.salesman_id and salesman.city='New York'
由于
答案 0 :(得分:1)
您应该查看数据库的执行计划,并且您将能够看到差异,但直接查询将具有相同或更好的性能,具体取决于您使用的SQL以及是否它足够聪明,能够理解它们是等同的。
同上语法注释。它应该是:
select *
from orders
join salesman
on orders.salesman_id = salesman.salesman_id
where salesman.city='New York';
答案 1 :(得分:1)
如果子查询返回多行,则MySQL将抛出错误。
SELECT ...
FROM orders o
WHERE o.salesman_id =
( SELECT s.salesman_id
FROM salesman s
WHERE s.city='New York'
)
也就是说,如果salesman
中有两行或多行'New York'
列中有city
,则查询会抛出错误。要解决这个问题,我们可以用IN
运算符替换相等比较。
如果我们将查询编写为JOIN操作,我们就不会遇到这个问题。我们还可以从salesman
表中返回列值。
给定合适的索引,我们期望查询执行计划是等效的,尽管在某些情况下它们可能不是。
最坏的情况是,使用子查询,执行计划将从orders
检索每一行,然后执行子查询以查明salesman
表中是否有一行用于该{ {1}}的城市值为salesman_id
。但是对于这个简单的案例,我们不会期望这样。
子查询是保存在SQL工具带中的强大工具。我们有理由选择使用子查询。
但是考虑到为此特定查询返回的结果,即使我们只需要从New York
表返回列,我们通常也会将其写为连接。
orders
(另外,我们通常避免使用旧式逗号运算符进行连接操作,并使用较新的(?)SELECT o.*
FROM orders o
JOIN salesman s
ON s.salesman_id = o.salesman_id
WHERE s.city='New York'
关键字,并将连接谓词移至JOIN
子句。)