这到底是什么 SQL 语句 - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
请不要在回答技术问题时复制粘贴 AI 生成的内容
movq
V2EX    程序员

这到底是什么 SQL 语句

  •  1
     
  •   movq 2021-07-12 21:32:24 +08:00 6004 次点击
    这是一个创建于 1551 天前的主题,其中的信息可能已经有所发展或是发生改变。

    有点看不懂下面的第一段语句。

    SELECT 后面不是接一个 output 吗?为什么可以在里面再写一个 SELECT ?

    SELECT (SELECT S.name FROM student AS S WHERE S.sid = E.sid) AS sname FROM enrolled as E WHERE cid='15-455' 

    第二段语句和第一段语句的效果是一样的,但是第二段就很好理解。把第二个 SELECT 的 output 作为 input 传递给 IN 函数。

    SELECT name FROM student WHERE sid IN ( SELECT sid FROM enrolled WHERE cid = '15-445' ) 

    这里面是原始表格:

    gA5OszQe4ZPySiw

    33 条回复    2021-07-19 08:30:28 +08:00
    akira
        1
    akira  
       2021-07-12 21:47:32 +08:00
    SELECT 后面不是接一个 output 吗?为什么可以在里面再写一个 SELECT ?
    把第二个 SELECT 的 output 作为 input 传递给 IN 函数。

    你自己的这 2 句话,再琢磨琢磨?
    xcstream
        2
    xcstream  
       2021-07-12 22:04:30 +08:00
    结果可以作为一个表
    WalkerCeng
        3
    WalkerCeng  
       2021-07-12 22:05:56 +08:00
    建议复习一下 MySQL
    movq
        4
    movq  
    OP
       2021-07-12 22:06:41 +08:00
    @akira 你的意思是第一个 query 里面,括号包着的那个部分,作为一个 output,传递给括号外面的 SELECT 吗?
    movq
        5
    movq  
    OP
       2021-07-12 22:06:56 +08:00
    @WalkerCeng 正在从 0 开始学
    JamesMackerel
        6
    JamesMackerel  
       2021-07-13 00:55:16 +08:00 via iPhone
    关键字:子查询
    Rocketer
        7
    Rocketer  
       2021-07-13 01:08:35 +08:00 via iPhone
    各个部分皆可子查询,只要输出的结果符合那个部分的格式即可
    xiangyuecn
        8
    xiangyuecn  
       2021-07-13 09:00:31 +08:00
    select (select count(...) from A ...) from B ... 这种写法 我这用的非常多 简直到了出神入化的境界 通用性极强 基本上无法用其他写法来改写 否则要么看不懂要么性能极低
    l0ve1o24
        9
    l0ve1o24  
       2021-07-13 09:07:44 +08:00
    @xiangyuecn 可以用外连接,然后 sum(case when A.id is not null then 1 else 0) ,我记得这样好像速度会快一点
    css3
        10
    css3  
       2021-07-13 09:12:27 +08:00   1
    发帖格式点赞,楼主需要看下 sql 最基础的语法
    dk7952638
        11
    dk7952638  
       2021-07-13 09:18:22 +08:00   1
    @xiangyuecn 这种写法可读性差,但性能真的比 join 要高很多
    qwer666df
        12
    qwer666df  
       2021-07-13 09:18:22 +08:00
    子查询的基操, 好几种变换格式, 贴个链接: https://www.cnblogs.com/CL-King/p/13730529.html
    aguesuka
        13
    aguesuka  
       2021-07-13 09:24:35 +08:00
    https://docs.oracle.com/cd/E11882_01/server.112/e41084/expressions013.htm#SQLRF52093
    Scalar Subquery Expressions

    这是为什么 SQL 没有静态安全的万恶之源之一
    xiangyuecn
        14
    xiangyuecn  
       2021-07-13 09:42:23 +08:00
    @l0ve1o24 #9 @dk7952638 #11 子查询是多个结果的聚合查询(留意我那个是 count,实际操作中是很多个带 count 的子查询),基本上无法用简单的 join 来改写,强行 join 结果集必然指数级暴增
    onionKnight888
        15
    onionKnight888  
       2021-07-13 10:11:52 +08:00
    我们业务系统如果用 oracle 的话,基本上都是这种子查询
    chanchan
        16
    chanchan  
       2021-07-13 10:27:41 +08:00
    垃圾 DSL 确实恶心
    aliveyang
        17
    aliveyang  
       2021-07-13 11:09:20 +08:00
    你把他看作程序一步一步执行就行了,只要格式输出符合,怎么玩都可以
    sytnishizuiai
        18
    sytnishizuiai  
       2021-07-13 11:35:54 +08:00
    这种可以写的,而且有时候情况复杂的时候还不得不这么写。

    不过你的问题描述的仔细,格式真不错,我之前提问,描述的没你直观。
    hanssx
        19
    hanssx  
       2021-07-13 11:39:35 +08:00
    确实有点反直觉,第 1 个是相关子查询,第 2 个是不相关子查询,如果相关子查询没优化的情况下,效率应该比不相关子查询低?
    way2explore2
        20
    way2explore2  
       2021-07-13 11:50:25 +08:00
    SUBQuery liao jie yi xia
    yolee599
        21
    yolee599  
       2021-07-13 12:37:57 +08:00 via Android
    这叫子查询,基本操作
    huigeer
        22
    huigeer  
       2021-07-13 12:39:06 +08:00
    万物皆可子查询
    levon
        23
    levon  
       2021-07-13 15:44:38 +08:00
    order by (select ....)
    landfill
        24
    landfill  
       2021-07-13 16:21:41 +08:00
    这是 andy pavlo 的课吗 我今天也刚看到这里
    movq
        25
    movq  
    OP
       2021-07-13 16:35:52 +08:00
    snw
        26
    snw  
       2021-07-13 17:37:36 +08:00 via Android   4
    其实吧,SQL 真实的逻辑顺序是:
    FROM ... //从某个表中
    WHERE ... //筛选出某些行
    SELECT ... //返回这些行的某些列的数据

    只是为了迎合英文的语法习惯所以规定成了 SELECT ... FROM ... WHERE ...

    所以改写一下就比较符合人类阅读了(虽然 SQL 会报错):

    FROM enrolled as E
    WHERE cid='15-455'
    SELECT (
    FROM student AS S
    WHERE S.sid = E.sid
    SELECT S.name
    ) AS sname
    zxCoder
        27
    zxCoder  
       2021-07-13 18:08:01 +08:00
    楼上的解释就比较清楚了
    zhangysh1995
        28
    zhangysh1995  
       2021-07-13 18:17:55 +08:00
    上面都没回答到点上。。
    楼主应该问的是为什么我们在一个子语句使用了外层的 E.sid 。
    这里需要知道表是否存在 index 。
    在有 index 的情况下,第一条语句首先 cid 过滤,然后再比较 S.did = E.sid 的时候,可以直接使用 index,速度比第二条的 IN 要快非常多。因为有 E.sid 的值可以直接 hash index 看 S.sid 的数据置是否存在,只有 E.sid 数量的比较次数 O(E.sid)。
    但是对于 IN 来说,它需要比每一条 S.sid 是否在 IN 后面的结果里面,没有 index 情况下 IN 的复杂度是 O(E.sid * S.sid),有 index 情况下 IN 的复杂度是 O(E.sid) 。
    这里说的都是理论的复杂度,实际数据库实现中 IN 不一定可以用 index 。
    另外一个区别是,因为第一条用了 scalar function, 在进行 cid 过滤的时候,满足的一行会直接送给子查询去判断 S.sid = E.sid 是否存在(这里是因为行变量的值可以传递到子查询),第二条是做完了过滤才去用 IN 查询,所以速度会变慢。
    zhangysh1995
        29
    zhangysh1995  
       2021-07-13 18:21:16 +08:00   1
    楼主如果要知道更多一些关于 SQL 的理论知识,可以考虑看 https://db.inf.uni-tuebingen.de/team/TorstenGrust.html 这位教授的课程,youtube 有视频。CMU 的课程重点是数据库系统本身和现代系统应用,而不是 SQL 。
    nook4sh
        30
    nook4sh  
       2021-07-13 18:51:21 +08:00 via Android
    @zhangysh1995 exists 也使用外层的字段,楼主应该问的就是 select 为什么也可以用子语句
    no1xsyzy
        31
    no1xsyzy  
       2021-07-14 09:51:12 +08:00   2
    @snw 准确地说不是为了迎合英文语法,而是因为它是拟似数学上的集合推导式 comprehension

    Y = { x | x ∈ X, x < 10 }
    SELECT x FROM X WHERE x < 10

    但是显然从数据流式处理角度描述要清晰准确地多,我不知道这语法是否存在歧义的情况,没有的话为什么各 SQL 引擎不进行两种语法同时支持呢?
    zbinlin
        32
    zbinlin  
       2021-07-18 19:35:29 +08:00
    @no1xsyzy 因为 `∈` 符号不好打
    no1xsyzy
        33
    no1xsyzy  
       2021-07-19 08:30:28 +08:00
    @zbinlin 我说的支持两种语法是
    SELECT ... FROM ... WHERE ...

    FROM ... WHERE ... SELECT ...
    关于     帮助文档     自助推广系统     博客     API     FAQ     Solana     5206 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 49ms UTC 09:25 PVG 17:25 LAX 02:25 JFK 05:25
    Do have faith in what you're doing.
    ubao snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86