今天看了下同事写的代码,才发现他居然喜欢把大量的逻辑写在 sql 语句里,跟他讲了下,他说是以前同事教的,我认为这样写可读性实在太差了,但是他也不愿意听我的!想听听各位大佬怎么讲。 下面是一段 sql
SELECT
m.id,
m.menuname,
m.link,
m.parent_id,
m.menutype,
m.sort
-- CASE
-- WHEN pm.parent_id > 0 THEN
-- 1 ELSE 0
-- END hasChildren
FROM
menu m
-- LEFT JOIN ( SELECT DISTINCT parent_id FROM menu ) pm ON pm.parent_id = m.id
WHERE
m.is_deleted = 0
<if test="userId !=null and userId !=''">
and m.id in (SELECT DISTINCT
rm.menu_id
FROM
role2menu rm
LEFT JOIN role r ON r.id = rm.role_id
LEFT JOIN user2role ur ON ur.role_id = r.id
WHERE
rm.is_deleted = 0
AND ur.user_id = #{userId} )
</if>
ORDER BY
m.sort
这只牵扯到 3 张表,就这么多 left join ,我后面又去翻了翻 10 来次 left join 的也很多。
1
liuliangyz 2022-02-21 16:42:30 +08:00 3
没吊事,等哪天上了 sql 筛查,这类逻辑写到 sql 当中的直接被干掉~
我觉得这类人特别二 |
2
x86 2022-02-21 16:48:05 +08:00
别管,听你的去改万一出啥问题,你也要分个锅
|
3
efaun 2022-02-21 16:49:08 +08:00
能 run 就行
|
4
levon 2022-02-21 16:51:22 +08:00 3
这 sql 不算复杂,而且不算是业务
|
5
gimp 2022-02-21 16:52:05 +08:00
“这个功能明天就要”
|
6
Jihua 2022-02-21 16:53:30 +08:00
没怎么写过 SQL 的菜鸟请教一下:对于同一个业务功能,把逻辑写到 SQL 里还是写到 SQL 外运行耗时更少?
|
8
est 2022-02-21 16:54:31 +08:00 31
这有啥不好的。sql 就是最古老的微服务,低代码啊。
最开始只有些教授发明了 B 树; 后来有穷 B 研究生把改成一个库可以被 C 语言调用 后来就有聪明商家包装成了一个 tcp 库拿出去卖钱 其次,后装市场为了迎合臭不要脸不懂技术分析师的需求,发明了 sql 没想到就火了。于是商家就把加上存储过程就是 RPC ,而且是 serverless 的小代码哦。insert/update/select/delete 对应 RESTful 的 CRUD ,sql 其实就是 GraphQL ,认证权限功能,分裤分婊功能,齐活了。 |
9
test3207 2022-02-21 16:54:33 +08:00 4
逻辑全写在代码里,都上事务吗?
多次 query 的额外网络和 IO 开销需要考虑吗? 有没有好哥哥讲一讲 |
10
felixcode 2022-02-21 16:56:06 +08:00 via Android
这样写可能不方便其它人维护,但用 join 的方式先做筛选再给程序的确是运算开销最小的。
|
11
nitmali 2022-02-21 16:58:35 +08:00 1
有一瞬间我以为我在看我们公司的代码 [doge]
|
12
woodensail 2022-02-21 17:00:25 +08:00 9
@Jihua 大多数情况下,还是数据库里更快一些,但是问题在于,应用服务器可以轻松的平行扩展,数据库可就难了。
所以一般是数据库先简单筛下,然后交给应用服务器做后续处理。 |
13
cando 2022-02-21 17:04:23 +08:00
挺正常的 习惯就好了
有时候复杂需求就需要这种 注意项目统一使用、语句优化好执行速度合理、写点注释 |
14
murmur 2022-02-21 17:05:30 +08:00
正常,我也听过这样的逻辑,sql 写业务,直接热发布不需要重启 tomcat
|
15
kiracyan 2022-02-21 17:07:10 +08:00 1
工业和老的系统很多逻辑都写在数据库存储过程 虽然可读性很差 但是是一种很廉价的 RPC 和热更新方案
|
16
SuperXRay 2022-02-21 17:09:12 +08:00
逻辑写在 sql 语句里有啥问题???
写一大坨业务代码就不恶心吗?就可读性好了吗? |
17
yazinnnn 2022-02-21 17:09:39 +08:00
以后业务量大了,俩表跑到不同的数据库上了咋整?
|
18
chenmobuys 2022-02-21 17:11:08 +08:00
这也算正常 SQL 吧,楼主还是没看到复杂的 SQL
|
19
Chad0000 2022-02-21 17:14:36 +08:00 via iPhone
只要给够钱就不是问题。我现在就涉及到这样的屎山代码,幸运的是我在海外,慢慢来,改好了反而是贡献的机会。
|
20
yor1g 2022-02-21 17:18:31 +08:00 7
又不是存储过程 一个小查询没啥问题 不能 join?不能子查询? 不如写下你的做法给大家看看
|
21
jeffxjh 2022-02-21 17:21:54 +08:00
想看不用连接查询的做法 大神给翻译翻译
|
22
ainyyy 2022-02-21 17:22:11 +08:00 2
我不觉得这个 sql 有什么问题。。 分开查询数据库更蠢吧。
|
23
kingwrcy 2022-02-21 17:29:16 +08:00
sql 没问题,你是不是对复杂有什么误解?
这个一次性能返回结果不是挺好? 你如果业务代码写也不见得别人能懂啥意思,sql 挺能表达你的业务的 |
24
leafre 2022-02-21 17:29:47 +08:00
“这只牵扯到 3 张表,就这么多 left join ,我后面又去翻了翻 10 来次 left join 的也很多。”
join 最多 3 张表,再多不合理 |
25
james2013 2022-02-21 17:31:12 +08:00
这个不算大量吧
当我看到有的统计 sql 各种 if 判断和 join,lefj join, 1 条 sql 语句竟然有 300 行+,看的都吐了 |
27
retrocode 2022-02-21 17:40:10 +08:00 1
这都是小 case,再烂的我都见过,有的厮直接 sql 里拼结构一个 sql 一两百行很正常.
你贴的这种写法有历史渊源的,有时候产品让加筛选,还特别急, 懒一点的人就是直接 sql 里改,然后丢 xml 上去更新 比如楼上说的 “这个功能明天就要” 早上提需求,中午问进度,第二天早上就要上线, 求稳定肯定是用改动最小的方法来的 不过恶心是真的恶心, 建议跑路, 我盲猜是政府项目 |
28
Paracosm 2022-02-21 17:42:39 +08:00
= = 。。。我经常写几百行的 sql ,不过我不是写后端的就是了
|
29
constantine008 2022-02-21 17:43:58 +08:00
我来支持下楼主,建议压测看看会不会有慢查询,像这种语句我估计大概率是慢查询,高并发情况下 CPU 很容易就打满
|
30
jsjjdzg 2022-02-21 17:44:31 +08:00
唉,写的搜索 Logstash 通道容器,全是复杂 SQL ,要一个 SQL 搜集各种上游数据,一点办法都没。。。
|
31
aliveyang 2022-02-21 17:44:36 +08:00
这个不算复杂吧,你是没看过银行存储过程的,那才是脑壳痛
|
32
muyiluop 2022-02-21 17:46:54 +08:00
借楼问一下,如果不用连表,但是查询字段又存在其他表中的情况,一般怎么做?
比如:a 、b 两个表,b 中存了 a 的 id ,查询 b 表时有个条件是 a 中的 name 字段 不连表我能想到的方法是:根据 name 条件查询出 a 的 id ,然后通过 b.aid in 的方式来查询 |
33
wudaye 2022-02-21 17:51:25 +08:00
SQL 层次不超过 2 层能接受,3 层就比较难受,适当的连表或子查询是合理的,但是你贴的这个 SQL 就有点过了,个人认为可维护性比性能重要得多
|
34
moxiaowei OP 上面有好几个喷子,麻烦看看标题好么?麻烦,那些觉得写 left join10 来次的是正常代码的,去问问你公司的 leader ,他允不允许,站在自己的角度上来想这个问题,简直是没脑子!你这样写纯属前人挖坑葬后人,坑了一波又一波!你也在这公司干不过 3 年!
|
35
moxiaowei OP @wudaye 终于看到了一个评论能看的,上面那些喷子只是为了完成任务,根本不为了长远发展,写写一大堆的业务逻辑到 sql 里面,后面人要看到吐血的!
|
37
acdfjelxe 2022-02-21 17:53:54 +08:00
各种场景几百行 SQL 都挺常见的,但你 SQL 得让数据库有优化空间 🌝
|
40
fisherwei 2022-02-21 17:57:53 +08:00
我这有个保存下来有 4MB 的 sql ,谁爱改谁改去,反正现在能用
|
42
wolfie 2022-02-21 17:58:52 +08:00 37
一点问题没有,就俩 left join 还是在子查询里。
一边觉得同事菜,同事应该听我的。 发到 v2 发现自己菜,v2 所有人应该听我的。 |
43
quan01994 2022-02-21 17:59:27 +08:00
见过更复杂的 。 最后的意见别改。
|
44
tabris17 2022-02-21 17:59:34 +08:00
谁写的谁改,你比他早跑路就行了
|
45
liprais 2022-02-21 18:01:32 +08:00
哈哈楼主这喷的两个 left join 里面只有一个是真 left join .....
|
46
InvincibleDream 2022-02-21 18:10:40 +08:00
假如你和同事都会 java 和 c ,而且项目里同时用两种语言。你会和同事讲 C 的代码可读性太差,不要再写了吗?
|
47
oneisall8955 2022-02-21 18:15:42 +08:00 via Android
代码和人,一个能跑就行
|
49
yeyang5211 2022-02-21 18:22:11 +08:00
这种简单的 join 写在代码里和 sql 里可读性都不差,
join 十几张表的逻辑拆成代码也不好看 可读性照样差,你看他查了十几次数据库, 筛选了一堆数据 经常读着读着不知道原来的目的了. 一般遇到这种我的倾向是拆成 3 个左右小一点的 sql, 代码清晰了, sql 也好读了. 别人写的屎山就当没看到了 , 改这种东西折寿. |
50
golangLover 2022-02-21 18:25:34 +08:00 via Android
可读性是一件事,debug 困难是更大的问题。我会要求他重写
|
51
deplivesb 2022-02-21 18:26:47 +08:00
这个 SQL 很复杂么?一个 leftjoin 就是个复杂的业务了?那你是没见过我司长达几百行的基础业务 SQL ,已经运行了好几年了,很稳定,可比你所谓的“把业务写在代码里”可读性强多了,维护起来也比又臭又长的代码方便。即使业务变更,前后对比 SQL 不比翻代码清晰?? OP 还在#34 楼喷别人干不过三年,我看你把复杂业务写成代码的你能干多少年。
|
52
ikas 2022-02-21 18:28:24 +08:00
看起来是权限表,除非你们用户非常的多..否则权限相关这点数据量 2 次 left join 没啥问题
当然..我看了下我们的代码是这样的.... select id,name,type from sys_resource where exists( select 1 from sys_role_resource where sys_resource.id = sys_role_resource.resource_id and exists( select sys_role.id from sys_role where sys_role_resource.role_id = sys_role.id and sys_role.id in ( select sys_user_role.id from sys_user_role where sys_user_role.user_id = :userId ) ) ) |
53
hidemyself 2022-02-21 18:36:15 +08:00
单单就这个 SQL 而言,不复杂,而且也没什么逻辑。
那种 ERP 和 OA 的项目里的 SQL ,才叫复杂 |
54
potatowish 2022-02-21 18:36:21 +08:00 via iPhone
SQL 语句尽可能不要包含太多逻辑,数据层就干数据层的事,逻辑应该放在应用层,包含大量逻辑的 SQL 短期看省事,长期非常难以维护,慢慢就成了没人敢动的屎山。
楼上不少人说什么不够复杂的,显然是偏题 |
55
efaun 2022-02-21 18:37:54 +08:00 1
lz 是真的菜, 而且还是不接受意见的菜 🤧 自己在小公司干了几个月, 见到没学过的东西就说不合理, 咋滴, 公司是你开的? 在 v2 找不到同水平的菜鸡(好像找到了一个?)认可就破防了, 咋滴, v2 是你建的?
|
56
fanchenio 2022-02-21 18:39:46 +08:00
我个人觉着楼主发的例子还算可以,没有多复杂或者大量逻辑,如果楼主觉着复杂或者逻辑繁杂的话,求贴出来一个解决方案,就按照你发的例子,如果你写代码要怎么写,虚心求教,想看一下。
|
57
guaguaguaxia1 2022-02-21 18:57:36 +08:00
反对楼主的都是真心的? SQL 语句里写逻辑看你后面怎么维护,屎山都是不经意间堆起来的,等你发现兜不住了再转身,屎山已经把你淹没
|
58
l00t 2022-02-21 19:02:01 +08:00
菜狗。这种程度的都觉得可读性差,是你的问题。
|
59
l00t 2022-02-21 19:02:46 +08:00
@guaguaguaxia1 写代码里怎么维护? SQL 代码也是代码,你能写在 Java 里维护,同样的逻辑写在 SQL 里就不会了么?
|
60
adoal 2022-02-21 19:06:43 +08:00 via iPhone
@moxiaowei 阿里那个什么 Java 规范里说连 JOIN 不得超过几个,是因为他们当时用的 MySQL ,对复杂 SQL 支持很差,多表连 JOIN 真的会搞死…但世间又不是只有 MySQL 这种残废。不说可读性、可维护性,只说性能,多表连 JOIN 根本不是 evil 。
|
61
Baloneo 2022-02-21 19:13:22 +08:00 1
```
SELECT DISTINCT a.meter_name AS meter_name, a.pro_name AS pro_name, a.pro_energy_val AS pro_energy_val_default, b.date AS date, sum(b.ep_o) AS counts FROM ( SELECT DISTINCT sh.collect_code AS collect_code, sh.address AS address, pee.meter_id AS meter_id, pee.meter_name AS meter_name, %s sum(sh.ep_o) AS ep_o FROM organization art LEFT JOIN organization arm ON arm.p_id=art.id LEFT JOIN product_energy_exp pee ON arm.id=pee.meter_id OR art.id=pee.meter_id LEFT JOIN area_collect ac ON ac.area_id=pee.meter_id LEFT JOIN collect_config_modbus ccm ON ccm.id=ac.collect_id INNER JOIN stat_hour sh ON sh.collect_code=ccm.collect_code AND sh.address=ccm.address WHERE 1=1 %s AND ac.calc = 1 AND sh.stat_time IS NOT NULL AND ccm.collect_code IS NOT NULL AND ccm.address IS NOT NULL %s ) b INNER JOIN ( SELECT DISTINCT ccm.collect_code, ccm.address, pee.pro_energy_val, pee.meter_id, pee.meter_name, pee.pro_energy_name AS pro_name FROM organization art LEFT JOIN organization arm ON arm.p_id=art.id LEFT JOIN product_energy_exp pee ON arm.id=pee.meter_id OR art.id=pee.meter_id LEFT JOIN area_collect ac ON pee.meter_id=ac.area_id LEFT JOIN collect_config_modbus ccm ON ccm.id=ac.collect_id WHERE 1=1 AND ac.calc = 1 %s ) a ON a.collect_code = b.collect_code AND a.address = b.address GROUP BY meter_name,pro_name,pro_energy_val,date ORDER BY meter_name,pro_name %s ``` |
62
whoisjohnlee 2022-02-21 19:28:02 +08:00 1
逻辑写 SQL 里面最大的问题是需要进行缓存优化的时候,DB 已经是最后一层了,想优化都没办法。。。
|
63
benzalus 2022-02-21 19:33:27 +08:00
业务逻辑丰富的 sql 可读性一般,调试困难,是我最不想碰的……
曾经见识过一个面向存储过程的 php 项目,项目里每个 sql 百行起步。业务增长越快,死得越快 |
64
ytmsdy 2022-02-21 19:47:27 +08:00
正常!以前很多 java 的项目,后端用的是 oracle ,很多业务逻辑都是写在存储过程里面。那个调试才叫一个痛苦!
有些大的存储过程,能打两张 A3 纸! |
65
Leviathann 2022-02-21 19:48:22 +08:00 via iPhone
还有统计类的 sql
大量用到 clickhouse 之类的内置函数 |
66
jellywong 2022-02-21 19:48:40 +08:00
不知道为什么这么多楼同意把业务逻辑放在 SQL 里的,我个人是不赞同这种方式,增加维护难度和踩坑风险。不知道大家是技术栈不同的原因,还是因为什么。
|
68
Leviathann 2022-02-21 19:54:11 +08:00 via iPhone
我们项目(公司后台)里会联表查的只有搜索条件巨多遍布几个表以及要分页的情况
其他的逻辑都不会写 sql 里 |
69
dcsuibian 2022-02-21 20:05:30 +08:00
啊啊啊?我赞同能跑就别乱动的观点,但可读性差这点还能有争论的?
|
70
idblife 2022-02-21 20:07:55 +08:00 via iPhone
还有把业务逻辑都封装在存储过程里的呢
|
71
wonderfulcxm 2022-02-21 20:19:31 +08:00 via iPhone 1
最近读桥水基金创始人瑞·达利欧的《原则》,经历一次倒闭级的失败后,他的思维转变从“我知道我是对的”,到“我怎么知道我的是对的。”。
楼主显然还停留在“我知道我是对的,如果你们说我错了,那我也是对的”上面。 |
72
notejava 2022-02-21 20:41:57 +08:00
这还好吧,那种查询复杂的管理后台,都是多张表 left join 的,代码少,需求变更时改动也快。
|
73
onhao 2022-02-21 20:55:31 +08:00
要不看看我这 5 张表的 SQL
https://wuhao.pw/archives/107/ https://wuhao.pw/archives/277/ 估计很多同仁看到这一堆的 SQL ,都要劝我,逻辑判断, 函数 ,存储过程 最好都别写到 sql 里 不过说实话,用了是真爽阿, 少写很多业务代码。 至于坑同事,或者后来者。 不至于坑,合适,不影响 sql 执行效率的逻辑判断, 函数 ,存储过程 带来极致的效率,如果这些特性都怕维护,而不用,那要这些特性干什么?存在即有其合理的地方。 |
74
gengchun 2022-02-21 21:25:29 +08:00
这条 SQL 其实不算太难理解吧?排版也不错。而且代码可读性,其实是有指标的,比如说变量或者函数名的长度和命名,排版时用是否对齐这些。业务逻辑是否用 SQL 为什么会和可读性有关系呢?
|
76
c6h6benzene 2022-02-21 21:38:47 +08:00 via iPhone
我觉得这 SQL 也不是太复杂啊,LEFT JOIN 的那个子查询可写可不写,反正也注掉了。你说真正有逻辑的部分就只有 WHERE 的那个 in 了吧,这也不难啊。
|
77
xy90321 2022-02-21 22:12:00 +08:00 via iPhone
稍微复杂点后台系统里,这种程度的 SQL 我们都是分给新人去开发测试的… 等你真看到的屎山一样十几张表揉在一起前前后后三四层左右结合内外连的时候再说吧… 而且一般这种屎山一样的 SQL ,换做程序实现更复杂…
|
78
Cbdy 2022-02-21 22:32:10 +08:00 via Android
两个有一个能跑就行(业界现状
|
79
vibbow 2022-02-21 22:45:38 +08:00
|
80
night98 2022-02-21 22:46:46 +08:00
@ikas 权限表这玩意完全没必要关联查。
1.数据量小,稍微有点要求的开发都会直接加载到内存 2.关联性弱,除了 user 和 role 的关联表数据量较大需要放到数据库查,其他的都可以直接走缓存查 综上所述你和楼主贴出来的 sql 都一般般 |
81
night98 2022-02-21 22:50:41 +08:00
给楼主提个建议,要么跑,要么当 leader 禁止此类写法,否则都是打工的,没必要提这个,有心思写好代码的同事,你不说他也会改,没心思的你说了反而得罪人家,要么赶紧跑路
|
82
Elietio 2022-02-21 23:12:28 +08:00
这算啥,我这一堆一二百行的 SQL ,需求整天变来变去,反反复复改了 N 次
|
83
chineselittleboy 2022-02-21 23:22:34 +08:00 via Android
能不能贴一下实现同样逻辑的代码
|
84
movieatravelove 2022-02-21 23:38:12 +08:00 via Android 2
互联网公司和传统 IT 公司的做法本身就是不同的,场景不一样,互相觉得对方是傻 x 倒也很正常
|
85
IvanLi127 2022-02-22 00:09:05 +08:00 via Android
你的示例,看起来问题不大
|
87
wangritian 2022-02-22 01:03:25 +08:00
以前看过有人吐槽教务系统的 sql ,鼠标滚轮滚坏了都拉不到底
|
88
wanacry 2022-02-22 01:43:32 +08:00 via iPhone
楼主你这培训班水平就别来秀了
|
90
dayeye2006199 2022-02-22 03:27:01 +08:00
LZ 了解过存储过程吗?这个可能比较符合 “业务逻辑“ 写在 sql 里面的定义。
多表联查其实也不算什么业务逻辑。 要看贵公司做什么业务的。需要大量水平扩展的,放太多重计算任务在数据库侧确实不太合适;如果是做 ERP 这类需要强关系建模的,每个表不设外键,禁止 join ,就看会不会被公司打死。。 软件公司也不是只有 2c 这一种的。 |
91
msg7086 2022-02-22 04:05:56 +08:00 via Android 1
遇到这种写法,我觉得最主要就提 3 个问题。
1. 这么写以后团队里是否有复数人有能力修改。公交车因素是很重要的,如果团队里只有一个人有能力这么写,就不能这么写。 2. 数据库是否需要横向扩展。应用服务器从 1 台变成 1000 台是比较容易的,数据库服务器从 1 台变成 2 台都比较难。这种结构能不能支撑以后的规模扩展? 3. 自动化测试能不能保证。大家都知道,自动化测试可以大幅减少工作量,降低加班时间和炸锅几率。超长 SQL 能否用足够的测试去覆盖各种情况?如果不可以,那么拆分成应用层逻辑就是值得的。我觉得存储过程不是很大的问题,但是存储过程也应该可自动化测试才行。 |
92
LeeReamond 2022-02-22 04:39:26 +08:00
所以这<if></if>语法是啥玩意,标准 sql 语法里有这个吗?
|
93
akira 2022-02-22 05:01:24 +08:00
看起来像是菜单权限的东西,这种数据量有限的东西,随便折腾的啊.
有一说一,程序员做的首要事情是让东西跑起来,其次才是需要考虑针对不同的情况进行处理。 |
94
cassyfar 2022-02-22 05:35:35 +08:00
这是什么妖风邪气啊
不单单是可读性差,主要在于水平扩展性差。不过如果你的服务 qps 不高,也不用太纠结。。。只是确实看着很捉急。 |
95
aragakiyuii 2022-02-22 08:09:09 +08:00
@LeeReamond #89 java mybatis 😂
|
97
sjzjams 2022-02-22 08:37:22 +08:00
我是菜鸟 想问这个 sql 哪里写了逻辑???哈哈哈
|
98
bthulu 2022-02-22 08:39:48 +08:00
现在都流行低代码了, 我司已经把业务全部重构到 sql 里了, 压根不用写代码了, 改改 sql 就好了, 真爽
|
99
sjzjams 2022-02-22 08:43:43 +08:00
@moxiaowei 这个是根据用户查询菜单和角色吧。楼主你要是贴个 10 来次 left join 的 sql 这样估计更能说明问题,站你的人会更多
|
100
l00t 2022-02-22 08:43:56 +08:00 1
@moxiaowei 嚯,菜狗急了。
我说你丫才多少点见识啊,就搁那逼逼可读性。是不是你看不懂看着累的就叫可读性不好?你咋不去大街上随便拉个人过来评评你自己的代码,问问他能不能看懂呢? 还特么数据库限制用 join ?关系型数据库就是为 join 而生,你不用 join ,那你为什么不直接用文本文件? |