登录

mysql - SQL问个基础例子,书上的,我怎么看都看不懂..谁帮我解释一下第2个为什么和第1个一样?

SELECT
    id,
    name,
    cid
from
    shbooks
where
    cid=(
        SELECT
            cid 
        FROM
            shbooks
        where
            name= '光荣与梦想'
        );

上面这个我完全看得懂,返回<光荣与梦想>的cid,然后用这个值作为条件,匹配整个表的cid;


SELECT
    b1.id,
    b1.name,
    b1.cid
from
    shbooks b1,
    shbooks b2 
where
    b1.cid=b2.cid
and
    b2.name='光荣与梦想';

但是这个,条件是 b1.cid=b2.cid 的话,会返回整个表,为什么加上个 b2.name='光荣与梦想' 就能返回 和 光荣与梦想 相同cid 的别的书???


答案不在长,也不在语言是不是准确,只要让我能明白怎么个逻辑就行了..谢谢了!

# MySQL
怪我咯 怪我咯 2559 天前 517 次浏览

全部回复(5) 我要回复

  • 天蓬老师

    天蓬老师2017-04-17 14:46:54

    原始

    b1.cid b1.name
    1     光荣与梦想
    2     另一本书
    1     梦想与光荣

    条件b1.cid = b2.cid(从9个结果中过滤得到5个结果)只要理解为什么是9个结果,整个问题应该也没有什么疑问了。

    b1.cid b1.name b2.cid b2.name
    1     光荣与梦想 1    光荣与梦想
    1     光荣与梦想 1    梦想与光荣
    2     另一本书   2    另一本书
    1     梦想与光荣 1    梦想与光荣
    1     梦想与光荣 1    光荣与梦想

    条件 b2.name='光荣与梦想'
    就得到

    b1.cid b1.name b2.cid b2.name
    1     光荣与梦想 1    光荣与梦想
    1     梦想与光荣 1    光荣与梦想
    

    我就是提问的的人,这是我补充的!
    我给大家解释解释到底是怎么回事,
    其实逻辑就是自己把自己当俩表;
    然后算自己的的笛卡尔集,
    然后再用第二个条件筛选!

    回复
    0
  • 巴扎黑

    巴扎黑2017-04-17 14:46:54

    你的第一种写法如果存在多条cid是不是就出错了?
    你可以参考下面的写法:

    /*子查询*/
    select id,name,cid 
      from shbooks 
    where cid in (select cid from shbooks where name='');
    
    --或者这种写法
    select id,name,cid
      from shbooks outerquery
    where cid exists  
      (select 1 from shbooks innerquery where outerquery.cid = innerquery.cid and innerquery.name='');
      

    至于你的第二种写法,你了解inner join吗?你看看下面的写法是不是更好懂些?

    select id,name,cid
      from shbooks main
      inner join (select cid from shbooks where name = '') child
      on main.cid = child.cid; 
    
    select id,name,cid
      from shbooks main
      inner join shbooks child on main.cid = child.cid
      where child.name = ''; 
    

    最后问问,你都是按书上例子写的?如果是,我建议最好不要看那本书了!

    回复
    0
  • ringa_lee

    ringa_lee2017-04-17 14:46:54

    条件是两个啊大兄弟,b2.name='光荣与梦想' 同时 b1.cid = b2.cid

    回复
    0
  • 迷茫

    迷茫2017-04-17 14:46:54

    看成两个不同的表就行,这是自联接

    回复
    0
  • 迷茫

    迷茫2017-04-17 14:46:54

    @碎镜 他的是正解,先笛卡尔集,然后进行筛选。这是是实现原理。不过一般这种语句SQL会自动优化。并不会真的先做出笛卡尔积然后进行筛选。

    回复
    0
  • 取消 回复 发送