1 sonice 2020-07-03 14:11:57 +08:00 这儿就震惊了?普普通通 |
![]() | 2 BrettD 2020-07-03 14:12:35 +08:00 via iPhone ![]() 这一坨怕不是复制粘贴搭出来的 |
![]() | 3 sunziren 2020-07-03 14:25:09 +08:00 ............,√ ............,× |
![]() | 4 jswxg 2020-07-03 14:25:51 +08:00 格式化后看就清楚很多了。 SELECT a.* FROM ( SELECT a.* FROM ( SELECT a.* FROM ( SELECT a.* FROM ( SELECT a.* FROM ( SELECT PLATFORM_REQUEST_CODE AS platformRequestCode, AGGTEGATE_REQUEST_CODE AS aggtegateRequestCode, CREATE_TIME AS createTime, STATUS AS payStatus, MERCHANT_GENERATE_CODE AS platformCode , USER_CODE AS buyCode, CHANNEL_NO AS channelNo FROM tb_aggtegate_payment_request WHERE STATUS != '00' AND DEL_FLAG = 0 AND IS_VALID = 0 ORDER BY CREATE_TIME DESC ) a LEFT JOIN ( SELECT CHANNEL_REQUEST_CODE AS channelOrderCode, AGGTEGATE_REQUEST_CODE AS channelaggtegateRequestCode FROM tb_channel_send_report WHERE DEL_FLAG = 0 ) b ON a.aggtegateRequestCode = b.channelaggtegateRequestCode ) a LEFT JOIN ( SELECT MERCHANT_INFO_CODE, MERCHANT_INFO_NAME AS platformName FROM tb_merchant_info WHERE DEL_FLAG = 0 ) c ON c.MERCHANT_INFO_CODE = a.platformCode ) a LEFT JOIN ( SELECT PLATFORM_USER_CODE, MERCHANT_NAME AS merchantName FROM tb_user_info WHERE DEL_FLAG = 0 ) b ON a.buyCode = b.PLATFORM_USER_CODE ) a LEFT JOIN ( SELECT CHANNEL_CODE, CHANNEL_NAME AS channelName FROM tb_channel_info WHERE DEL_FLAG = 0 ) b ON a.channelNo = b.CHANNEL_CODE ) a LEFT JOIN ( SELECT AGGTEGATE_REQUEST_CODE, TIME_END AS payTime FROM tb_wxpay_order_business WHERE DEL_FLAG = 0 AND IS_VALID = 0 ) b ON a.aggtegateRequestCode = b.AGGTEGATE_REQUEST_CODE WHERE 1 = 1 |
![]() | 5 aaronlam 2020-07-03 14:27:15 +08:00 这就震惊了,想当年我刚接触到我们公司计费系统的 SQL 代码时,整个人都不好了。 |
![]() | 6 airplayxcom 2020-07-03 14:27:42 +08:00 ![]() 1=1 就很灵性了 |
![]() | 7 loading 2020-07-03 14:28:40 +08:00 via Android ![]() @airplayxcom 1=1 是标准的拼接 sql 常用技巧 |
![]() | 9 takemeaway 2020-07-03 14:31:55 +08:00 挺好的项目,就是写这个项目的人脑子太直了 |
![]() | 11 luxinfl OP @takemeaway 话说不是不应该用这么多连接么,阿里巴巴开发手册上面还禁止使用连接 |
![]() | 13 est 2020-07-03 14:38:40 +08:00 ![]() 新人和老人的区别就是面对一坨屎山,新人会大吃一斤。老人会贤淑的避开最臭的那部分屎,然后灵巧的在保证屎山不垮的情况下把自己的屎再拉一层上去 |
14 cbasil 2020-07-03 14:39:05 +08:00 太复杂,join 多的查询建视图啊, |
16 laminux29 2020-07-03 14:45:22 +08:00 DBA 不懂编程思维,不懂调试测试,写出 shi 一样的 SQL,很正常。 你受不了可以自己改。 |
18 rtp 2020-07-03 14:51:17 +08:00 这才哪到哪,我记得原来的公司,写统计方面的 sql,基本上都是一条语句几屏幕啊…… |
19 soulzz 2020-07-03 14:52:09 +08:00 牛皮 用 sql 语句写业务 估计真的是老开发才会干的蠢事 |
![]() | 20 z960112559 2020-07-03 14:52:43 +08:00 @est 666 |
![]() | 21 Vegetable 2020-07-03 14:54:03 +08:00 @airplayxcom 1=1 的确挺蛇皮的,我不喜欢,为了保证 where 后边不空添加一个 true,我不敢说这算是技巧,这算是补丁。 |
![]() | 24 526326991 2020-07-03 15:00:18 +08:00 就这? |
![]() | 25 baozhuo 2020-07-03 15:00:41 +08:00 via iPhone 这就震惊了?你知道我当初实习的时候见到同事有一个功能,他写了一个接近 6000 行的存储过程的时候有多震惊吗?当时有幸在那个项目组,后来把分配给我的东西做完我就溜了,差点自闭了 |
![]() | 29 leonardyang 2020-07-03 15:11:32 +08:00 ![]() 从 sql 角度看还好吧,主要是写的可读性有点差,我很讨厌一屏都放不完的 sql 。关键是表结构是谁设计的,也是新人? join 多不多不就看表结构设计吗,按学校数据库课程教的那套范式必然一堆 join 啊,从设计时候就应该考虑冗余字段减少关联查询,没有对新人做的表设计做 review ? |
![]() | 30 pikaconan 2020-07-03 15:13:43 +08:00 弱弱的问一下,实际开发一般 sql 写多长... |
32 xxlee 2020-07-03 15:14:57 +08:00 left join 取 a.*,这和取最里面那层 select a.* 有啥区别呢?最后再加一个 where 1=1 。。。。 实在无法吐槽 |
33 toesbieya 2020-07-03 15:17:55 +08:00 为啥会觉得写的没问题啊,这 5 层嵌套 `select` 有什么意义,和 `left join ... left join` 有什么区别 |
![]() | 34 leonardyang 2020-07-03 15:21:03 +08:00 |
![]() | 35 EricFuture 2020-07-03 15:23:40 +08:00 这个还才一屏不到,习惯就好了 |
![]() | 36 pomelotea2009 2020-07-03 15:30:00 +08:00 via Android 这才 join 五次啊,不过嵌套的五次比较少见。所以开发要对业务有一定的了解,这种情况一般优先考虑把不可变字段做冗余,其次考虑为了取一两个字段要去 join 整个表的那一两个字段做冗余,即使该字段是可变的(当然表少数据量小无所谓) |
37 xxlee 2020-07-03 15:33:34 +08:00 ![]() @leonardyang 他这种取法,和最里面那层 a.*是一样的 |
![]() | 38 Xusually 2020-07-03 15:33:46 +08:00 不知道表结构,索引设置什么的。 单看 sql 问题似乎不是非常大 |
![]() | 39 vxlol 2020-07-03 15:35:21 +08:00 这种程度的 SQL 就惊了。。 比这还夸张的在我以前待的一大型制造企业 ERP 系统里比比皆是~ 业务逻辑基本都在存储过程,随便拎一个就是几百上千行~ 尤其是财务模块,存储过程里面使用游标、递归、动态 SQL 、嵌套执行其它存储过程什么的,都见识过~ |
![]() | 40 luxinfl OP @pomelotea2009 有三张表是基础信息,其实可以单独在代码里面查询后再匹配塞值。应该比连接三个表要快 |
![]() | 43 magicdu 2020-07-03 15:38:37 +08:00 via Android 太年轻了,见过格式化都格式化不出来的 SQL 吗 |
![]() | 46 leonardyang 2020-07-03 15:49:32 +08:00 ![]() @luxinfl 没看懂你的想法,所谓的匹配塞值不还是要遍历数据吗,莫非你是觉得自己用代码实现的“left join”比现代数据库的查询优化强?互联网公司要求少用 join 是用冗余字段实现的,不是靠在代码里再遍历一遍这种自欺欺人的方式。。。 |
![]() | 47 Jrue0011 2020-07-03 15:49:41 +08:00 看起来中间有几个表目的是为了获取 xxx_name 给前端用于显示,如果在 name 允许用户修改即会改变的情况下,有什么好的做法吗。。。 |
![]() | 48 nutting 2020-07-03 15:50:46 +08:00 sql 就这德性,很恶心的 |
![]() | 49 winglight2016 2020-07-03 15:54:31 +08:00 这种子查询嵌套,我们一般用来人工减慢响应时间的,方便以后优化。。。 哈哈,开玩笑了,不过,子查询是需要尽量避免的吧,实在不行搞个动态视图也好呀。 |
![]() | 50 Xusually 2020-07-03 15:55:27 +08:00 @luxinfl 光你贴出来的这个 sql 看没有明显的问题。 执行效率高还是低,肯定还是得看表结构以及索引的安排啊。 你可以实际执行一下,并且也查看一下这条 sql 在 db 的执行计划,看看情况。 光看 sql 本身没办法看出来效率有多低 |
![]() | 51 est 2020-07-03 15:57:57 +08:00 这么多人点赞。怕了怕了。 |
52 x66 2020-07-03 16:11:39 +08:00 我觉得还好吧,做互联网业务的人跟做 ERP/银行 /保险业务的人平常遇到到的业务复杂度不是同一个级别的。 |
![]() | 53 LuciferGo 2020-07-03 16:19:53 +08:00 真这么写吧,要是每个关联都是命中索引问题倒也不大,丑是丑了点 |
55 Alexisused 2020-07-03 16:47:16 +08:00 之前用的报表系统一个报表只能写一个 sql, 最大的那个报表 SQL 写出来压缩之后还有 8K 字符,varchar2 存不下,后来没办法分成了 2 个报表.. |
56 zypy333 2020-07-03 16:53:08 +08:00 看到长 sql 就头大,楼主能贴出来优化后的 sql 吗 |
![]() | 57 F281M6Dh8DXpD1g2 2020-07-03 17:00:02 +08:00 via iPhone 要喷也要看了执行计划做了 profile 再喷 阿里那手册看看就算了,毕竟 mysql 就那样 |
![]() | 58 ReinerShir 2020-07-03 17:28:20 +08:00 一般是业务复杂,开发时间少,而且对性能没啥要求的后台功能才这么写 |
59 markyangd 2020-07-03 17:29:33 +08:00 via iPhone 见过 3000 行 sp 的人表示,你这个 sql 语句算小菜。 |
![]() | 60 WytheHuang 2020-07-03 17:33:29 +08:00 这样格式化,能看了~ SELECT a.* FROM ( SELECT a.* FROM ( SELECT a.* FROM ( SELECT a.* FROM ( SELECT a.* FROM ( SELECT PLATFORM_REQUEST_CODE AS platformRequestCode, AGGTEGATE_REQUEST_CODE AS aggtegateRequestCode, CREATE_TIME AS createTime, STATUS AS payStatus, MERCHANT_GENERATE_CODE AS platformCode, USER_CODE AS buyCode, CHANNEL_NO AS channelNo FROM tb_aggtegate_payment_request WHERE STATUS != '00' AND DEL_FLAG = 0 AND IS_VALID = 0 ORDER BY CREATE_TIME DESC ) a LEFT JOIN ( SELECT CHANNEL_REQUEST_CODE AS channelOrderCode, AGGTEGATE_REQUEST_CODE AS channelaggtegateRequestCode FROM tb_channel_send_report WHERE DEL_FLAG = 0 ) b ON a.aggtegateRequestCode = b.channelaggtegateRequestCode ) a LEFT JOIN ( SELECT MERCHANT_INFO_CODE, MERCHANT_INFO_NAME AS platformName FROM tb_merchant_info WHERE DEL_FLAG = 0 ) c ON c.MERCHANT_INFO_CODE = a.platformCode ) a LEFT JOIN ( SELECT PLATFORM_USER_CODE, MERCHANT_NAME AS merchantName FROM tb_user_info WHERE DEL_FLAG = 0 ) b ON a.buyCode = b.PLATFORM_USER_CODE ) a LEFT JOIN ( SELECT CHANNEL_CODE, CHANNEL_NAME AS channelName FROM tb_channel_info WHERE DEL_FLAG = 0 ) b ON a.channelNo = b.CHANNEL_CODE ) a LEFT JOIN ( SELECT AGGTEGATE_REQUEST_CODE, TIME_END AS payTime FROM tb_wxpay_order_business WHERE DEL_FLAG = 0 AND IS_VALID = 0 ) b ON a.aggtegateRequestCode = b.AGGTEGATE_REQUEST_CODE WHERE 1 = 1 |
![]() | 61 xhf1024 2020-07-03 17:40:53 +08:00 请问你们是基于自己的快速平台开发的嘛 |
![]() | 62 kiracyan 2020-07-03 17:44:12 +08:00 看着恐怖而已 逻辑挺简单的 |
63 protectione055 2020-07-03 17:48:10 +08:00 via Android @leonardyang ??原来学校教的那套范式都没用的吗?刚被数据库这套东西折磨完 |
64 lwlizhe 2020-07-03 17:51:23 +08:00 我是个客户端开发,接触的数据库查询没到这个量上 但是,之前有时被拉去开后端事故总结会的时候,时常听到子查询导致的种种慢查询……(我个人感觉子查询本身没啥问题,应该归属于子查询的查询索引问题吧,不知道这么说对不对) 记得后端老大还总结了一下数据库查询的几个注意点……可惜现在都忘了…… |
65 hello826 2020-07-03 17:54:07 +08:00 这个代码评审能过吗 |
67 KasonPasser 2020-07-03 18:31:06 +08:00 |
![]() | 68 loading 2020-07-03 18:33:07 +08:00 via Android @KasonPasser 用 1=1 可以满足洁癖在最后替换掉,你用 1 不好做。 |
![]() | 70 Qusic 2020-07-03 20:14:33 +08:00 via iPhone 这叫为未来预留优化空间( |
![]() | 71 GBdG6clg2Jy17ua5 2020-07-03 20:15:20 +08:00 via iPhone @luxinfl #11 不要被阿里什么规范洗脑,适合自己业务的才是最好的。 |
![]() | 72 rockyou12 2020-07-03 20:20:12 +08:00 虽然这个 sql 本身就很屎,但 mysql 不支持 with 让这个 sql 更屎了。希望大家以后都不要再用 mysql,pg 真的好用很多…… |
![]() | 74 rainysia 2020-07-03 22:50:19 +08:00 以前有个 oracle 的师傅...不写代码, 就直接写 SQL 给我。 大概平均一个 select 从开始到结束有个几千行吧。 中间各种生成, 变换, 计算, 叠加。 跟着写了两年。 各种黑魔法学的盆满钵满 |
![]() | 75 justin2018 2020-07-03 22:53:06 +08:00 |
![]() | 76 NoString 2020-07-04 01:46:14 +08:00 哈哈哈 这种在我们组大概会被枪毙 |
![]() | 77 levelworm 2020-07-04 05:52:54 +08:00 via Android 话说如果是 BI 的话可以考虑用 dbt 这个工具 |
![]() | 78 cozof 2020-07-04 06:48:19 +08:00 via iPhone 以前写存储过程或者看别人的存储过程很多都是上百行,不过这个 abcd 的表别名不怎么样。 |
![]() | 79 collery 2020-07-04 09:29:33 +08:00 hive sql 经常这么写。连表查 |
![]() | 80 lovecy 2020-07-04 14:35:17 +08:00 SELECT a.* FROM ( SELECT a.* FROM ( SELECT a.* FROM ( SELECT a.* FROM ( SELECT a.* FROM ( SELECT PLATFORM_REQUEST_CODE AS platformRequestCode , AGGTEGATE_REQUEST_CODE AS aggtegateRequestCode , CREATE_TIME AS createTime , STATUS AS payStatus, MERCHANT_GENERATE_CODE AS platformCode , USER_CODE AS buyCode , CHANNEL_NO AS channelNo FROM tb_aggtegate_payment_request WHERE STATUS != '00' AND DEL_FLAG = 0 AND IS_VALID = 0 ORDER BY CREATE_TIME DESC ) `a` LEFT JOIN ( SELECT CHANNEL_REQUEST_CODE AS channelOrderCode, AGGTEGATE_REQUEST_CODE AS channelaggtegateRequestCode FROM tb_channel_send_report WHERE DEL_FLAG = 0 ) `b` ON a.aggtegateRequestCode = b.channelaggtegateRequestCode ) `a` LEFT JOIN ( SELECT MERCHANT_INFO_CODE, MERCHANT_INFO_NAME AS platformName FROM tb_merchant_info WHERE DEL_FLAG = 0 ) `c` ON c.MERCHANT_INFO_CODE = a.platformCode ) `a` LEFT JOIN ( SELECT PLATFORM_USER_CODE, MERCHANT_NAME AS merchantName FROM tb_user_info WHERE DEL_FLAG = 0 ) `b` ON a.buyCode = b.PLATFORM_USER_CODE ) `a` LEFT JOIN ( SELECT CHANNEL_CODE, CHANNEL_NAME AS channelName FROM tb_channel_info WHERE DEL_FLAG = 0 ) `b` ON a.channelNo = b.CHANNEL_CODE ) `a` LEFT JOIN ( SELECT AGGTEGATE_REQUEST_CODE, TIME_END AS payTime FROM tb_wxpay_order_business WHERE DEL_FLAG = 0 AND IS_VALID = 0 ) `b` ON a.aggtegateRequestCode = b.AGGTEGATE_REQUEST_CODE WHERE 1 = 1 |
![]() | 81 lovecy 2020-07-04 14:51:19 +08:00 ``` 啊哈哈哈哈,没有效果啊,白格式化了大半天,貌似 markdown 语法也无效 ``` |
![]() | 82 shakoon 2020-07-04 18:23:56 +08:00 说实话我没看懂这个拉屎人的目的,left join 一堆东西但最后都没有用到 join 得到的字段。 SELECT AA.PLATFORM_REQUEST_CODE AS PLATFORMREQUESTCODE, AA.AGGTEGATE_REQUEST_CODE AS AGGTEGATEREQUESTCODE, AA.CREATE_TIME AS CREATETIME, AA.STATUS AS PAYSTATUS, AA.MERCHANT_GENERATE_CODE AS PLATFORMCODE, AA.USER_CODE AS BUYCODE, AA.CHANNEL_NO AS CHANNELNO FROM TB_AGGTEGATE_PAYMENT_REQUEST AA LEFT JOIN TB_CHANNEL_SEND_REPORT BB ON BB.DEL_FLAG = 0 AND AA.AGGTEGATE_REQUEST_CODE = BB.CHANNELAGGTEGATEREQUESTCODE LEFT JOIN TB_MERCHANT_INFO CC ON CC.DEL_FLAG = 0 AND CC.MERCHANT_INFO_CODE = AA.MERCHANT_GENERATE_CODE LEFT JOIN TB_USER_INFO DD ON DD.DEL_FLAG = 0 AND AA.USER_CODE = DD.PLATFORM_USER_CODE LEFT JOIN TB_CHANNEL_INFO EE ON EE.DEL_FLAG = 0 AND AA.CHANNEL_NO = EE.CHANNEL_CODE LEFT JOIN TB_WXPAY_ORDER_BUSINESS FF ON FF.DEL_FLAG = 0 AND FF.IS_VALID = 0 AND AA.AGGTEGATE_REQUEST_CODE = FF.AGGTEGATE_REQUEST_CODE WHERE AA.STATUS != '00' AND AA.DEL_FLAG = 0 AND AA.IS_VALID = 0 ORDER BY AA.CREATE_TIME DESC |
![]() | 83 shakoon 2020-07-04 18:33:17 +08:00 |
![]() | 84 realpg PRO 以前在一个公司招聘 PHP,有一个 JAVA 开发商业软件转过来的大佬。 面试题有一个数据库结构跟所要的查询结果格式比较蹩脚的题,基本考察就是性能考虑,这么进行交叉,循环设计 这个大佬拿笔记本摆弄了半天,非常牛逼的特意给我炫耀他接这题的方式,一条 2KB 的 SQL 语句拼接…… 那还是跑在笔记本的测试库下本身也就几十万数据量下,一个查询卡了能有 0.5 秒…… |
![]() | 85 pydiff 2020-07-05 11:27:49 +08:00 是我的话我直接扔回给写的人,看着就觉得恶心 |