• 请不要在回答技术问题时复制粘贴 AI 生成的内容
wh469012917
V2EX  ›  程序员

为什么很多人连基础的 SQL 都写不好,却开口闭口就是缓存架构分布式?

  •  6
     
  •   wh469012917 · Sep 2, 2021 · 21147 views
    This topic created in 1795 days ago, the information mentioned may be changed or developed.

    说下情况,我们公司同个部门的好几个同事,连个基础的 SQL 都写不好,代码中一堆数据库 N+1 的问题,连个 WHERE IN 查询都不会用,涉及到批量查询,都是遍历然后一条条的去跑 SQL,同一个方法重复查询了好几次,数据库设计更是不行,外键都是用逗号分隔拼接成字符串,然后保存到主表上。

    正因为 SQL 写的烂,所以接口性能很差劲,但是他们好像都不在意这些 IO 方面的优化,整天在想着怎么优化语言性能,比如反射、JSON 序列化、语言基础库的性能;要么就是上集群、加缓存,然后又没有任何设计模式,直接业务代码中强硬加入缓存读写,就算是缓存也是先从缓存读出数据,然后遍历一条条去数据库再查出来,性能更差了

    其实整体项目量不大,好好写好 SQL,基本上能搞定 90% 的性能问题了,大部分的开发经验也都好几年了,不至于这种基础知识点不懂,可为啥就是不重视 SQL 性能

    206 replies    2021-09-11 20:47:45 +08:00
    1  2  3  
    xinJang
        101
    xinJang  
       Sep 3, 2021
    @summerLast 试了下,空指针。
    我本身 sql 是个模糊搜索的查询,里面本来就有 left join 语句,可能不适合我这种场景
    Canon1014
        102
    Canon1014  
       Sep 3, 2021
    还不是被逼的
    qrobot
        103
    qrobot  
       Sep 3, 2021   ❤️ 2
    因为 SQL 写的再好,比如中间件的一次缓存命中, 如果缓存命中率达到 90% 以上, 那么就不存在 IO 问题。


    ```
    正因为 SQL 写的烂,所以接口性能很差劲,但是他们好像都不在意这些 IO 方面的优化,整天在想着怎么优化语言性能,比如反射、JSON 序列化、语言基础库的性能;要么就是上集群、加缓存,然后又没有任何设计模式,直接业务代码中强硬加入缓存读写,就算是缓存也是先从缓存读出数据,然后遍历一条条去数据库再查出来,性能更差了
    ```

    我不清楚你们的项目结构,不过 IO 在怎么优化是有瓶颈的,为了提高命中缓存, 我觉得不用 in 和 left join 是最好的
    dbpe
        104
    dbpe  
       Sep 3, 2021   ❤️ 2
    @xinJang 现在我是用..jooq 或者 querydsl 去解决...不过我还是尽量单表查询,然后去合并查询请求...list 遍历去查不靠谱
    Akiya
        105
    Akiya  
       Sep 3, 2021
    这个你得怪市场需求,不要怪同事,公司招什么样的人,就会得到什么样的人
    dr1q65MfKFKHnJr6
        106
    dr1q65MfKFKHnJr6  
       Sep 3, 2021
    技术面试到面试数据库知识的时候 分两种, 一种给个场景直接问 SQL 怎么写, 另外一种是问你数据库集群 balabala,
    wh469012917
        107
    wh469012917  
    OP
       Sep 3, 2021
    @qrobot 但是我们数据量并不大,并发也不高,基本上写好 sql 能处理大部分场景了,缓存架构什么的等业务起来了再搞也不迟
    xinJang
        108
    xinJang  
       Sep 3, 2021
    @xinJang 不能使用自己的 sql 查询 不然就空指针 无解
    followyourheart
        109
    followyourheart  
       Sep 3, 2021
    @ipwx #66 你说的这种临时表 不应该是我们优化的对象 避免产生临时表吗
    hhjswf
        110
    hhjswf  
       Sep 3, 2021
    我们总监不让用 join 的...n+1 怎么避免..
    xinJang
        111
    xinJang  
       Sep 3, 2021
    @dbpe 没看太明白。如果你是先查单表,拿到的数据是一个 list 吧,这时你不遍历查询怎么组合数据?这里还有个问题,那就是分页数据,组合之后的数据长度有时是不一致的,那就会变成翻第 2 页只有 1 条数据的可能
    flybluewolf
        112
    flybluewolf  
       Sep 3, 2021
    @hhjswf 笑死,关系型数据库这么多年理论研究都白搞?不要 join,那还玩什么集合论?所有关系型数据库都移除 join 操作好了!具体项目具体研究,基本上 99%的项目关系型数据库足够满足要求,性能问题都能通过 sql 语句+索引解决。
    flybluewolf
        113
    flybluewolf  
       Sep 3, 2021
    @dcoder 动则都分布式? CPA 咋解决?
    followyourheart
        114
    followyourheart  
       Sep 3, 2021
    @hhjswf #110 查出来 list1 然后获取 idList 根据 idList 一次性查出数据集合 Map<id,Object>,然后遍历 list 根据 id 从 Map 取出数据,组装数据,不知道有没有更好的方法
    yt28
        115
    yt28  
       Sep 3, 2021
    因为 SQL 写不好,所以张口闭口就是缓存架构分布式!
    dream4ever
        116
    dream4ever  
       Sep 3, 2021
    @wh469012917 他们这个智商,就告别这一行吧
    l00t
        117
    l00t  
       Sep 3, 2021   ❤️ 2
    @vjnjc 我们面试有一道 SQL 题,大致是这样的,有一个学生表,一个科目表,一个考试成绩表。让用一条语句找出所有科目成绩在 80 分以上的学生。

    看起来很简单吧? 9 成的面试者没法写对。
    skinny
        118
    skinny  
       Sep 3, 2021
    现在这行不就流行堆砌分布式、集群、高并发、高性能、高可用等等这些看似高大上名词的风气吗?

    连那些云服务大厂都一个鸟样,吹起来什么异地灾备、自动化、高可用有多少个 9,崩起来就 N 小时还全面崩
    followyourheart
        119
    followyourheart  
       Sep 3, 2021
    @l00t #117 查出最低分大于 80 的 group by 不就行了吗
    dream4ever
        120
    dream4ever  
       Sep 3, 2021
    @sagaxu 我一同事负责的一项业务有不少 SQL 查询,前一段时间发现服务器 CPU 经常飙到 100%,排查来排查去发现一堆慢查询,最后追根溯源发现数据库各个表所有被查询到的字段都没有设置索引……
    zhouyou457
        121
    zhouyou457  
       Sep 3, 2021
    简直就是在说我司的开发!

    手上的项目有 n 多一句 sql 完成的功能,什么先查出 id 再 in 查询,各种拼接子查询,结果合并计算、标准时间格式化成前端格式字符串,然后结果集一律字符串返回,连封装都懒得写,直接 Map<String,String>
    wh469012917
        122
    wh469012917  
    OP
       Sep 3, 2021
    @l00t 为什么要设计一个成绩表?是因为一个学生一个科目,可能存在多次考试吗?如果是的话,所有科目成绩 >= 80 是指这个科目的每次成绩,还是某一次成绩?
    zgcwkj
        123
    zgcwkj  
       Sep 3, 2021
    @zhouyou457 先查询出 ID,可能是嵌套的 sql 会影响性能吧,我试过直接用 in(selete id) 的时候会特别慢的。我认为不能直接否定,得看需求。嵌套的查询很影响 sql 性能的,从而影响其他的业务
    l00t
        124
    l00t  
       Sep 3, 2021
    #122 就一次考试
    l00t
        125
    l00t  
       Sep 3, 2021
    另外你的 ID 是不是犯禁啊。一 @就会触发验证。是不是 69 两个数字导致的?
    l00t
        126
    l00t  
       Sep 3, 2021
    咦好像也不是,这次就没触发
    ytmsdy
        127
    ytmsdy  
       Sep 3, 2021
    @xz410236056 DBA 一般是解决数据库底层的一些性能问题,比如说 cache 命中率过低,根据情况设置索引,设置一些联合主键等问题。但是到开发层面的基础 SQL 编写,一般是不会介入的,要不然 DBA 要累死!
    l00t
        128
    l00t  
       Sep 3, 2021
    @followyourheart 题很简单,能写对的十不存一,我也很惊讶。
    ytmsdy
        129
    ytmsdy  
       Sep 3, 2021
    @l00t 第一眼看到这个问题,我也愣住了。后来想了想,直接把 80 分一下的学生排除掉就可以了!
    ytmsdy
        130
    ytmsdy  
       Sep 3, 2021
    现在的开发越来越脱离底层开发,上手就是 ORM 一般梭哈,连 SQL 都不需要会,也能做 CRUD 。
    从另外一个方面来看,越来越多非科班出身,直接在培训班速成出来的开发人员,虽然看着很唬人,但是涉及到一些具体算法,数据库设计,性能分析就完全抓瞎了。
    公司的管理层也只管功能上线能用就好了,技术层面的代码实现,业务逻辑处理完全不会!
    Brentwans
        131
    Brentwans  
       Sep 3, 2021
    的确,特别是去有钱但是 IT 部门没什么事的客户,很多小问题数据库完全可见处理的,一定要上 XXX 项目。我曾经处理过一个客户,处理 XXX 一定要上 spark,但是机器就 3 台老服务器,内存 16G...无所谓的,你可以想一下为什么这个破机器要上 Spark ?达到目的皆大欢喜
    解决问题有的方法简单,有复杂的,有些看似简单实际运维复杂,有的还有利益关系。甚至有时候刚好研发同学最近看了某些工具或者方案,于是就用了。
    我现在觉得最终能够稳定解决问题的方案,至少不算差,至于其他的不太重要了。
    Cbdy
        132
    Cbdy  
       Sep 3, 2021 via Android
    但是,代码写得好,有用吗?

    事实是没用,所以写得烂

    自己的项目当然可以好好写,但将心比心,大多数人都是外出务工的农民工,能跑通过验收老板能接受就行了,何况还有 996 、PUA 、拖欠工资、251 能大山压着呢

    至于分布式集群、消息队列这种听起来高大上的东西当然要背得头头是道,这样才能提高身价,让老板满意,让面试官满意
    Veneris
        133
    Veneris  
       Sep 3, 2021
    唱个反调,有一部分愿意是这样的。

    复杂 sql 可维护性差,绝大部分公司的绝大部分业务,都不会对 sql 如此苛刻,命中索引足够了。

    但是人员的流动却是常事,业务逻辑都在代码里会更好上手,随便找个实习生也能接手代码。

    项目的平稳发展比所谓的写好 sql 更重要。
    lap510200
        134
    lap510200  
       Sep 3, 2021
    小公司小项目就这样,很多人写代码, 表面上运行没问题,但是 ide 报各种警告异常,像我这种洁癖的人,看着很难受,看都懒得看,很多还不是科班的,有的人还比较倔的,不好说的
    Macolor21
        135
    Macolor21  
       Sep 3, 2021
    @hhjswf 看一下 GraphQL 怎么解决 N+1 的,用 DataLoader,核心思想是 @followyourheart 提到的,list1 拿到里面的关联键,通过这个键( id )集合用 in 一条查询出来,然后映射成 Map<id,List Or Object>
    cassyfar
        136
    cassyfar  
       Sep 3, 2021
    其实我觉得挺正常的,大厂挺多人都没机会接触 sql 了。选择后端数据库都是 nosql 的。
    wh469012917
        137
    wh469012917  
    OP
       Sep 3, 2021
    @Cbdy 代码写得好是没用,但是写得烂就有用吗?“996 、PUA 、拖欠工资、251” 这些问题不会因为你代码写的烂就能解决。而且相对好的代码,后续自己维护和版本迭代,对开发效率之类都是有好处的
    wh469012917
        138
    wh469012917  
    OP
       Sep 3, 2021
    @Veneris 你去试试一个,n+1 查询,命中索引,看看整体的时间怎么样就知道了
    Cbdy
        139
    Cbdy  
       Sep 3, 2021 via Android   ❤️ 1
    @wh469012917 写得好的代码要花时间,写得烂的代码可以更快出活,这样就可以 996,避免 700,剩下一天休息一下舒缓一下 PUA 的压力,至于后续维护和版本迭代,就管不了这么多了,谁知道后续还是不是原作者维护和迭代呢

    我不是说这是对的实践,但是业界事实,毕竟成年人的世界没有对错,只有打工
    rsyjjsn
        140
    rsyjjsn  
       Sep 3, 2021
    理想情况是每个人都好好写 sql,其实 bug 会更少,但是有用吗?现在的招聘动不动就是分布式集群以及 k8s,工作了 1 年,这些总得去学去实践吧,那怎么实践呢?那当然是在现成的项目里面实践啊,难不成我写了 1 年代码,整天研究 sql 怎么写更加快?面试官可不会问你那么多 sql 相关问题。
    zhuichen
        141
    zhuichen  
       Sep 3, 2021
    主要是看你们部门 leader 怎么看这个问题,如果 care 的话,你就可以提出来,就有机会发展,不过这么久了,我估计大概率不 care,久而久之就这样了
    adoal
        142
    adoal  
       Sep 3, 2021 via iPhone
    这就是所谓的“互联网公司”
    pcmgr456
        143
    pcmgr456  
       Sep 3, 2021 via Android
    @l00t 中枪了😂
    lanlanye
        144
    lanlanye  
       Sep 4, 2021
    看完两页希望有人来解个惑:为什么说数据量大的场景下联表会有坑?有的话常用的解决方式是什么?
    wellsc
        145
    wellsc  
       Sep 4, 2021
    报我身份证得了
    wqtacc
        146
    wqtacc  
       Sep 4, 2021
    wellsc
        147
    wellsc  
       Sep 4, 2021
    啊不对 我对“天在想着怎么优化语言性能,比如反射、JSON 序列化、语言基础库的性能;要么就是上集群、加缓存,然后又没有任何设计模式” 也是很方案,后端还是操作系统更重要的,而不是编译原理
    dcoder
        148
    dcoder  
       Sep 4, 2021
    @wellsc 就是被楼主 @wh469012917 吐槽的同事么?
    vishun
        149
    vishun  
       Sep 4, 2021
    @l00t
    先在考试成绩表中查找分数大于 80 的按用户分组的个数,然后再和科目总个数比较?
    ```
    select user_id from (
    select count(*) as num,user_id from 成绩表 where score >80 group by user_id
    ) as t
    where t.num = (select count(*) from 科目表)
    ```
    xuanbg
        150
    xuanbg  
       Sep 4, 2021
    @l00t 这貌似和科目表没啥关系啊。。。

    select s.name from score a
    join student b on b.id = a. student_id
    group by a.student_id
    having min(a.score) > 80;
    cnbattle
        151
    cnbattle  
       Sep 4, 2021
    想知道 lz 理解的基础的 SQL 包含哪些? 我目前基本不用子查询 jion 以及视图 存储过程啥的
    crazycarry
        152
    crazycarry  
       Sep 4, 2021
    你接触的太少,c 端基本就是查询 es 或者 redis 的数据了
    xingheng
        153
    xingheng  
       Sep 4, 2021
    @Actrace #100 什么坑? 用不好是人和流程的问题。
    fengpan567
        154
    fengpan567  
       Sep 4, 2021
    @xuanbg 是不是得把 name 加到 group by 里额
    wellsc
        155
    wellsc  
       Sep 4, 2021
    @dcoder
    JasonLaw
        156
    JasonLaw  
       Sep 4, 2021 via iPhone
    @l00t #117 可以的话,把表结构发出来一下
    snw
        157
    snw  
       Sep 4, 2021 via Android
    @xuanbg
    *所有科目*成绩在 80 分以上
    wh469012917
        158
    wh469012917  
    OP
       Sep 4, 2021 via iPhone
    @zhuichen 部门领导自己没写代码,之前我有委婉提出过这个问题,领导意思就是说要改,但是他也没去推动这件事,我大概就知道他意思了
    wh469012917
        159
    wh469012917  
    OP
       Sep 4, 2021 via iPhone
    @cnbattle 我理解的基础,就是要懂得怎么避免 n+1 的问题,以及在合适的场景下用 join 查询,以及 where in 查询。这里“合适的场景”的定义是:通过主键的集合查询列表,可以使用 where in 来,而不是遍历集合一条条 where id =?这样
    wh469012917
        160
    wh469012917  
    OP
       Sep 4, 2021 via iPhone
    @crazycarry 如果数据量不大百万级别,并发量也不大,加 es 或者 redis 的意义在哪里?
    veike
        161
    veike  
       Sep 4, 2021 via Android
    @wh469012917 领导跟你感受估计一样,想改也改不了
    857681664
        162
    857681664  
       Sep 4, 2021 via Android
    @l00t 这题比较标准的解法是 join 表后 group by 学生 id 再 having 分数> 80 分的数=科目数吧,而且还要考虑到有学生没考过试的
    ericbize
        163
    ericbize  
       Sep 4, 2021
    那是因为你没见过 一个 select * 可以完事的,别人 select 第一列 ,select 第二列 ,select 第三列 (每次只出一个数据那种)
    alexkkaa
        164
    alexkkaa  
       Sep 4, 2021
    这叫快餐式开发
    mynamewang0
        165
    mynamewang0  
       Sep 4, 2021
    @l00t 这样写应该可以吧,没运行。应该不需要用到聚合函数
    select * from student std
    where not exist (
    select 1 from subject sbj
    inner join scorce sc
    on sc.subjectId = sbj.subjectId
    where std.studentId = sbj.studentId
    and sbj.scorce < 80
    )
    2i2Re2PLMaDnghL
        166
    2i2Re2PLMaDnghL  
       Sep 4, 2021
    话说起来,不记得是谁,推荐任何人想要学第二门语言都应该学 SQL
    争什么 Python Go JavaScript 什么的,第二门语言最应该是 SQL
    不少人推荐第二门语言采用不同的范式;而 SQL 可以说是目前生产环境上广泛运用的唯一一门描述式语言了。

    顺便摘个发言:『如果你的同事全都不如你,那么是你该跳槽的时候了』
    s04
        167
    s04  
       Sep 4, 2021
    @Cbdy 扎心了
    sunznx
        168
    sunznx  
       Sep 4, 2021
    IT 行业盛产臭鱼烂虾
    namelosw
        169
    namelosw  
       Sep 4, 2021
    N + 1 是基础 + 原则问题,这个都不当回事要我我就铁拳了。这个达不到,谈别的都是吹逼。

    就算不喜欢写 SQL,也得搞 batch 解决这个问题才行。

    至于 SQL 为啥经常被忽视是因为 SQL 逼格比分布式低,用得早,想到 DBA 和存储过程就能想到那些老掉牙的项目。所以人们都喜欢拿分布式包装自己。
    onhao
        170
    onhao  
       Sep 4, 2021
    @l00t
    没有表结构 斗胆现丑
    select * from 学生表 where uid in(
    select uid from 成绩表 where 分数>=80 group by uid)
    potatowish
        171
    potatowish  
       Sep 4, 2021 via iPhone
    面试主要就问这些啊,现在面三年以上的几乎没有笔试,谈起 SQL 优化头头是道,真要是手写没几个能过的
    iseki
        172
    iseki  
       Sep 4, 2021
    总觉得是一些公司推广自己的“规范”,加上一些人无视实际情况盲目使用其他公司的规范导致的麻烦。我相信制定这些规范的程序员知道自己在干什么,但是我非常质疑那些盲目执行这些规范的人知不知道自己在干什么。
    anouser
        173
    anouser  
       Sep 4, 2021
    好奇你们这个产品有多少人在使用?
    msg7086
        174
    msg7086  
       Sep 4, 2021
    N+1,项目初期,或者量小的时候,可以不用优化。
    但是数据量大了,开始针对热点优化的时候,还不知道去改,那是真的不应该。
    当然,有些坑不亲自跳一次是不知道的,这些人可能就是经验太少,没跳过这坑,你只要不提他们就根本不知道要这么做。
    xuanbg
        175
    xuanbg  
       Sep 4, 2021
    @onhao 你这个写错了,学生只要有一门考过 80 就符合条件了。要先按学生分组,取最小值,最小值也高于 80 就没毛病了。所以要用 having 去筛而不是 where 。
    leafre
        176
    leafre  
       Sep 4, 2021
    面向面试编程
    unregister
        177
    unregister  
       Sep 4, 2021
    sql 不一定要用 join,我目前都是单表查的,再用 dto 组装也可以。
    JerryCha
        178
    JerryCha  
       Sep 4, 2021
    因为这是时尚
    你不跟着走,哪怕性能好也是落伍
    shot
        179
    shot  
       Sep 5, 2021   ❤️ 1
    > 我们公司同个部门的好几个同事

    多个成员存在这样的问题,说明这是团队(负责人)的问题,而不是孤立的某几个人的问题。

    如果要从团队层面系统地解决这个问题,推荐两个实践:
    1 )引入压力测试 /性能优化,对于数据量千万级以下的传统应用,要求单机支持 1k+ tps 、100- ms latency,可以在设计 /开发 /测试环境快速识别性能瓶颈,避免低质量的设计和开发;
    2 )引入 Application Performance Monitoring 工具,数字化直观展现应用在生产环境的性能瓶颈,将慢操作视为高优先级技术债务,对应的产品有 SkyWalking 、New Relic 等等。

    通过建立体系化的开发流程,即使新的工程师加入时没有相关的经验和意识,处理几次相关问题后也能逐渐适应和融入。
    当然,这对团队负责人的技术能力和管理能力要求就比较高了。
    如果楼主部门领导不具备这种能力,楼主描述的问题必然会反复出现。
    noparking188
        180
    noparking188  
       Sep 5, 2021
    有库表设计和 SQL 规范嘛
    glfpes
        181
    glfpes  
       Sep 5, 2021
    SQL 写好并不容易,做一个 sql boy 比 crud 要困难。

    服务治理其实就是 crud
    ychost
        182
    ychost  
       Sep 5, 2021
    高并发+大流量 本质是 DB 、缓存 的使用,语言层面能够优化的性能微乎其微
    cyru1s
        183
    cyru1s  
       Sep 5, 2021
    还不是各个大厂面试官逼得。

    实际工作:在 Druid 之类的存储上写类 SQL 的 DSL 、往往还因为公司版本过低不支持最新文档的 functions,最终你要合理的把查询拆成几个然后本地处理中间数据、最终完成一个功能。

    面试提问:缓存架构分布式。
    wh469012917
        184
    wh469012917  
    OP
       Sep 5, 2021
    @anouser 用户量大概十几万吧,日活 1 万左右,做垂直领域的,量不算多,但是还是有用户用的
    wh469012917
        185
    wh469012917  
    OP
       Sep 5, 2021
    @namelosw 对的,解决一个 n+1 问题,比你用什么架构缓存都好使,除非就是为了装逼
    wh469012917
        186
    wh469012917  
    OP
       Sep 5, 2021
    @msg7086 因为 n+1 问题,我们目前部分接口已经出现明显的性能问题了,但是有些人都不重视这块,一直在优化语言级别的性能
    wh469012917
        187
    wh469012917  
    OP
       Sep 5, 2021
    @unregister 也可以,join 不是万能,解决问题的方案有很多种,
    wh469012917
        188
    wh469012917  
    OP
       Sep 5, 2021
    @shot 团队负责人虽然也是技术出身,但是自己并不写代码,主要是注重开发进度和应用稳定性,技术主要让组内一个有一定年限的同事来处理,但是这代码就是这个同事写出来了,所以就不要指望他能做啥优化了。

    目前数据量在三千万左右,每个月增长差不多 200w 左右,sql 性能问题已经慢慢显露出来了。
    wh469012917
        189
    wh469012917  
    OP
       Sep 5, 2021
    @noparking188 无,一个数据库出现 4 种字符集,join 都用不了;字段命名没有规则,大家各做各的
    wh469012917
        190
    wh469012917  
    OP
       Sep 5, 2021
    @ychost 对的,数据库是 IO 最重的地方,应该花大力气来处理;加缓存虽然效果明显,但是会导致代码复杂度增加和缓存同步问题
    msg7086
        192
    msg7086  
       Sep 6, 2021
    楼上说的对,出现这些问题,但是同事都不懂,那应该搞一些研讨会学习会,让一两个懂的人出来给其他人讲解一下。然后 leader 也应该制定规范,让大家知道哪些东西是必须要遵守的。
    从你说的来看,这两个 leader 都有些问题,工作没有做好,导致下面拉稀。
    wh469012917
        193
    wh469012917  
    OP
       Sep 6, 2021
    @msg7086 前提是要有人懂,并且有一定的话语权来推动呀;我们这边部门领导一般不管这些,主要负责全局的把控;后端组长自己就是写这些代码的人;我是一直想要推动,奈何没什么话语权,所以挺难的
    wh469012917
        194
    wh469012917  
    OP
       Sep 6, 2021
    @noparking188 一个数据库出现了四五种字符集,你觉得能有什么规范吗
    noparking188
        195
    noparking188  
       Sep 6, 2021
    @wh469012917 #194 不大懂你说的四五种字符集什么意思,是 collate character ?
    如果是,在规范里指定用哪种就行,原先不统一的字符集后面陆续更改,解决历史遗留问题
    onhao
        196
    onhao  
       Sep 6, 2021
    @xuanbg 题主好像是说
    “找出所有科目成绩在 80 分以上的学生。
    难道是我理解错误?
    BiChengfei
        197
    BiChengfei  
       Sep 6, 2021
    @l00t 这不是本科《数据库原理》中的 demo 吗?我会写,我是不是面试通过了,嘿嘿嘿
    create table t_student (
    id integer primary key ,
    name varchar(40)
    );

    create table t_course (
    id integer primary key ,
    course varchar(40)
    );

    create table t_grade (
    id integer primary key ,
    student_id integer,
    course_id integer,
    grade integer
    );

    insert into t_student(id, name) values (1, '张三');
    insert into t_student(id, name) values (2, '王五');
    insert into t_student(id, name) values (3, '小李');
    insert into t_student(id, name) values (4, '王华');

    insert into t_course(id, course) values ( 1, '数学' );
    insert into t_course(id, course) values ( 2, '语文' );
    insert into t_course(id, course) values ( 3, '英语' );
    insert into t_course(id, course) values ( 4, '化学' );
    insert into t_course(id, course) values ( 5, '物理' );

    insert into t_grade(id, student_id, course_id, grade) values ( 1, 1, 1, 100 );
    insert into t_grade(id, student_id, course_id, grade) values ( 2, 1, 2, 80 );
    insert into t_grade(id, student_id, course_id, grade) values ( 3, 1, 3, 10 );
    insert into t_grade(id, student_id, course_id, grade) values ( 4, 1, 4, 100 );
    insert into t_grade(id, student_id, course_id, grade) values ( 5, 1, 5, 100 );

    insert into t_grade(id, student_id, course_id, grade) values ( 6, 2, 1, 100 );
    insert into t_grade(id, student_id, course_id, grade) values ( 7, 2, 1, 100 );
    insert into t_grade(id, student_id, course_id, grade) values ( 8, 2, 1, 100 );
    insert into t_grade(id, student_id, course_id, grade) values ( 9, 2, 1, 100 );
    insert into t_grade(id, student_id, course_id, grade) values ( 10, 2, 1, 100 );

    select
    a.student_id,
    b.name
    from t_grade a
    left join t_student b on a.student_id = b.id
    left join t_course c on a.course_id = c.id
    group by a.student_id
    having min(a.grade) >= 80
    stevenbipt
        198
    stevenbipt  
       Sep 6, 2021
    基础的 sql 都写不好,简单的调优分析都做不好就谈那些理论上的这种操作个人是接受不了,就算接口慢优化也要分析好哪些地方该优化,而不是直接上理论安排上一堆东西,存储过程这些复杂的做不好问题不大,但是基础的 sql 查询都写得烂那还是建议换一家不用关系型数据库的公司吧
    l00t
        199
    l00t  
       Sep 6, 2021
    @mynamewang0 你这个 inner join 没意义啊……
    @onhao “所有” 修饰 科目……
    @BiChengfei left join course 这步不对

    @xuanbg 加科目表是因为有人可能缺考。当然这个也基于一个没考就没记录的假设。如果没考也有一条得分为 0 的记录,那科目表有没有也没关系。我一般会在追问时才要求考虑没考就没记录的情况。你这条语句的思路是对的,但是写得太随意了,过不了语法编译的……

    @vishun 我一般不会这么写,但是你这样写也行……反正结果是对的……
    BiChengfei
        200
    BiChengfei  
       Sep 6, 2021
    @l00t 之前的不对是因为没有考虑缺考吗,大意了

    -- t_student 、t_course 全连接,然后左连接成绩表,缺考就为 null
    select
    a 。id,
    a 。name
    from t_student a
    left join t_course b on true
    left join t_grade c on a 。id = c 。student_id and b 。id = c 。course_id
    group by a 。id
    having min(c 。grade) >= 80;

    -- t_grade 左连接 t_student,通过学生 id 分组,然后最低分和参考课程数过滤
    select
    a 。id,
    b 。name
    from t_grade a
    left join t_student b on a 。student_id = b 。id
    group by a 。student_id
    having
    min(a 。grade) >= 80
    and count(a 。course_id) = (select count(*) from t_course);

    第一种是第一想法,但会占用额外的内存,第二种会好很多

    请不要在每一个回复中都包括外链,这看起来像是在 spamming
    我只能把点换成句号
    1  2  3  
    About   ·   Help   ·   Advertise   ·   Blog   ·   API   ·   FAQ   ·   Solana   ·   975 Online   Highest 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 182ms · UTC 22:55 · PVG 06:55 · LAX 15:55 · JFK 18:55
    ♥ Do have faith in what you're doing.