SQL中的子查询VS直接查询

时间:2016-06-06 20:46:37

标签: sql

我正在尝试回答这个问题:(常规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'

由于

2 个答案:

答案 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子句。)