这些SQL查询之间有什么区别吗?

时间:2012-05-31 01:19:00

标签: mysql sql

他们做同样的事情,但我想知道是否存在一些差异,我的意思是表现......

TB1 :     tb1_id - > PK     ...

TB2 :     tb1_id - > FK     ...

select columns ... from tb1 a left join tb2 b
    on a.tb1_id=b.tb1_id and b.uid=xxxxxxx where a.tb1_id=yyy limit 1

select columns ... from tb1 a left join tb2 b
    on a.tb1_id=b.tb1_id where a.tb1_id=yyy and b.uid=xxxxxxx limit 1

感谢。

4 个答案:

答案 0 :(得分:2)

稍微简化一下你可以认为首先评估你的JOIN,然后应用WHERE s过滤器。使用这个公式:

1)您的第一个查询将返回表a中的所有记录以及表b中的相应记录(如果存在,否则为一组NULL s)具有匹配的{{ 1}}和tb1_id字段中的某个值。然后,结果集将被过滤为仅包含uid的记录,并将第一条记录返回给客户端。

2)您的第二个查询将返回表a.tb1_id=yyy中的所有记录以及表a中的相应记录(如果存在,否则为一组b s)具有匹配的{{ 1}}。结果集将被过滤掉,只包含NULL中具有特定值的记录以及tb1_id中的特定值。最后一部分很重要。此特定条件将丢弃表a.tb1_id中仅{1}}中没有匹配集的所有记录,仅仅因为b.uid。基本上,你不会在a中混合b和“硬”条件。执行此操作后,您会立即将NULL != xxxxxxx加入转换为LEFT JOIN加入。剩余集合的第一条记录将返回给客户。

那就是说,在你的情况下你可能会得到相同的结果。无独有偶。您的查询中没有WHERE,因此返回的记录顺序取决于数据库引擎(您最好不要认为它不具有确定性且无法依赖,它很可能是如此并且恰好可能发生这样的情况:两个查询返回的第一个记录是匹配所有条件的记录 - OUTERINNER中的ORDER BY匹配以及{{1}在tb1_id中。

答案 1 :(得分:1)

在没有注意到JOIN的'LEFT'部分之后,我怀疑我原来的答案。经过一些快速研究后,我修改了我的答案。

这个article详细解释了一些事情,表明查询的实际处理方式不同。

以下文中的示例显示了这一点。

mysql> SELECT * FROM product LEFT JOIN product_details
   ON (product.id = product_details.id)
   AND product_details.id=2;
+----+--------+------+--------+-------+
| id | amount | id   | weight | exist |
+----+--------+------+--------+-------+
|  1 |    100 | NULL |   NULL |  NULL |
|  2 |    200 |    2 |     22 |     0 |
|  3 |    300 | NULL |   NULL |  NULL |
|  4 |    400 | NULL |   NULL |  NULL |
+----+--------+------+--------+-------+
4 rows in set (0.00 sec)

mysql> SELECT * FROM product LEFT JOIN product_details
   ON (product.id = product_details.id)
   WHERE product_details.id=2;
+----+--------+----+--------+-------+
| id | amount | id | weight | exist |
+----+--------+----+--------+-------+
|  2 |    200 |  2 |     22 |     0 |
+----+--------+----+--------+-------+
1 row in set (0.01 sec)

答案 2 :(得分:1)

他们不一样。请参阅@Pavel_Veller提供的答案这只是为了支持他的回答。在Postgres上运行:

create table tb1( tb1_id int );
create table tb2( tb1_id int, uid int );

insert into tb1 values( 1 );

insert into tb2 values( 1, 0 );

select a.tb1_id
  from tb1 a left join tb2 b on a.tb1_id = b.tb1_id and b.uid = 3
  where a.tb1_id = 1;

select a.tb1_id
  from tb1 a left join tb2 b on a.tb1_id = b.tb1_id
  where a.tb1_id = 1
    and b.uid = 3;

结果:

postgres=#     select a.tb1_id
postgres-#       from tb1 a left join tb2 b on a.tb1_id = b.tb1_id and b.uid = 3
postgres-#       where a.tb1_id = 1;
 tb1_id
--------
      1
(1 row)


postgres=#     select a.tb1_id
postgres-#       from tb1 a left join tb2 b on a.tb1_id = b.tb1_id
postgres-#       where a.tb1_id = 1
postgres-#         and b.uid = 3;
 tb1_id
--------
(0 rows)

答案 3 :(得分:0)

这两个查询完全没有相同的做法,第一个查询可能不会从b返回任何行,而第二个查询不会从a返回任何行,如果没有b的有效连接则返回b。

Mysql解释where子句中的“=”,好像它是一个INNER连接(它不是连接,但在这种情况下使用的方式相同)