今天看了下同事写的代码,才发现他居然喜欢把大量的逻辑写在 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

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} )

ORDER BY
m.sort

这只牵扯到 3 张表,就这么多 left join ,我后面又去翻了翻 10 来次 left join 的也很多。

没吊事,等哪天上了 sql 筛查,这类逻辑写到 sql 当中的直接被干掉~
我觉得这类人特别二

别管,听你的去改万一出啥问题,你也要分个锅

能 run 就行

这 sql 不算复杂,而且不算是业务

“这个功能明天就要”

没怎么写过 SQL 的菜鸟请教一下:对于同一个业务功能,把逻辑写到 SQL 里还是写到 SQL 外运行耗时更少?

这非要堆到 10 来个 left join 搞死 sql 才算复杂么?

这有啥不好的。sql 就是最古老的微服务,低代码啊。

最开始只有些教授发明了 B 树;

后来有穷 B 研究生把改成一个库可以被 C 语言调用

后来就有聪明商家包装成了一个 tcp 库拿出去卖钱

其次,后装市场为了迎合臭不要脸不懂技术分析师的需求,发明了 sql
没想到就火了。于是商家就把加上存储过程就是 RPC ,而且是 serverless 的小代码哦。insert/update/select/delete 对应 RESTful 的 CRUD ,sql 其实就是 GraphQL ,认证权限功能,分裤分婊功能,齐活了。

逻辑全写在代码里,都上事务吗?
多次 query 的额外网络和 IO 开销需要考虑吗?
有没有好哥哥讲一讲

这样写可能不方便其它人维护,但用 join 的方式先做筛选再给程序的确是运算开销最小的。

有一瞬间我以为我在看我们公司的代码 [doge]

大多数情况下,还是数据库里更快一些,但是问题在于,应用服务器可以轻松的平行扩展,数据库可就难了。
所以一般是数据库先简单筛下,然后交给应用服务器做后续处理。

挺正常的 习惯就好了
有时候复杂需求就需要这种
注意项目统一使用、语句优化好执行速度合理、写点注释

正常,我也听过这样的逻辑,sql 写业务,直接热发布不需要重启 tomcat

工业和老的系统很多逻辑都写在数据库存储过程 虽然可读性很差 但是是一种很廉价的 RPC 和热更新方案

逻辑写在 sql 语句里有啥问题???
写一大坨业务代码就不恶心吗?就可读性好了吗?

以后业务量大了,俩表跑到不同的数据库上了咋整?

这也算正常 SQL 吧,楼主还是没看到复杂的 SQL

只要给够钱就不是问题。我现在就涉及到这样的屎山代码,幸运的是我在海外,慢慢来,改好了反而是贡献的机会。

又不是存储过程 一个小查询没啥问题 不能 join?不能子查询? 不如写下你的做法给大家看看

想看不用连接查询的做法 大神给翻译翻译

我不觉得这个 sql 有什么问题。。 分开查询数据库更蠢吧。

sql 没问题,你是不是对复杂有什么误解?

这个一次性能返回结果不是挺好?

你如果业务代码写也不见得别人能懂啥意思,sql 挺能表达你的业务的

“这只牵扯到 3 张表,就这么多 left join ,我后面又去翻了翻 10 来次 left join 的也很多。”

join 最多 3 张表,再多不合理

这个不算大量吧
当我看到有的统计 sql
各种 if 判断和 join,lefj join, 1 条 sql 语句竟然有 300 行+,看的都吐了

10 来个 join 就搞死?如果不是 MySQL 的话没那么怕多 join 的。

这都是小 case,再烂的我都见过,有的厮直接 sql 里拼结构一个 sql 一两百行很正常.

你贴的这种写法有历史渊源的,有时候产品让加筛选,还特别急, 懒一点的人就是直接 sql 里改,然后丢 xml 上去更新

比如楼上说的 “这个功能明天就要”

早上提需求,中午问进度,第二天早上就要上线, 求稳定肯定是用改动最小的方法来的

不过恶心是真的恶心, 建议跑路, 我盲猜是政府项目

= = 。。。我经常写几百行的 sql ,不过我不是写后端的就是了

我来支持下楼主,建议压测看看会不会有慢查询,像这种语句我估计大概率是慢查询,高并发情况下 CPU 很容易就打满

唉,写的搜索 Logstash 通道容器,全是复杂 SQL ,要一个 SQL 搜集各种上游数据,一点办法都没。。。

这个不算复杂吧,你是没看过银行存储过程的,那才是脑壳痛

借楼问一下,如果不用连表,但是查询字段又存在其他表中的情况,一般怎么做?
比如:a 、b 两个表,b 中存了 a 的 id ,查询 b 表时有个条件是 a 中的 name 字段
不连表我能想到的方法是:根据 name 条件查询出 a 的 id ,然后通过 b.aid in 的方式来查询

SQL 层次不超过 2 层能接受,3 层就比较难受,适当的连表或子查询是合理的,但是你贴的这个 SQL 就有点过了,个人认为可维护性比性能重要得多

上面有好几个喷子,麻烦看看标题好么?麻烦,那些觉得写 left join10 来次的是正常代码的,去问问你公司的 leader ,他允不允许,站在自己的角度上来想这个问题,简直是没脑子!你这样写纯属前人挖坑葬后人,坑了一波又一波!你也在这公司干不过 3 年!

终于看到了一个评论能看的,上面那些喷子只是为了完成任务,根本不为了长远发展,写写一大堆的业务逻辑到 sql 里面,后面人要看到吐血的!

你牛逼 对你我是真的很佩服的

各种场景几百行 SQL 都挺常见的,但你 SQL 得让数据库有优化空间 🌝

我说不能了?主观臆想啥呢?自嗨?

贴你写的 sql 出来 问问下个接受的想不想打你

我这有个保存下来有 4MB 的 sql ,谁爱改谁改去,反正现在能用

喜欢把逻辑写数据库的人其实是 DBA 而不是码农

一点问题没有,就俩 left join 还是在子查询里。

一边觉得同事菜,同事应该听我的。

发到 v2 发现自己菜,v2 所有人应该听我的。

见过更复杂的 。 最后的意见别改。

谁写的谁改,你比他早跑路就行了

哈哈楼主这喷的两个 left join 里面只有一个是真 left join .....

假如你和同事都会 java 和 c ,而且项目里同时用两种语言。你会和同事讲 C 的代码可读性太差,不要再写了吗?

代码和人,一个能跑就行

我们数据库老师做的项目就这样,一条 SQL 语句占好几屏,还说这是标准,都看吐了

这种简单的 join 写在代码里和 sql 里可读性都不差,
join 十几张表的逻辑拆成代码也不好看 可读性照样差,你看他查了十几次数据库, 筛选了一堆数据
经常读着读着不知道原来的目的了.
一般遇到这种我的倾向是拆成 3 个左右小一点的 sql, 代码清晰了, sql 也好读了. 别人写的屎山就当没看到了 , 改这种东西折寿.

可读性是一件事,debug 困难是更大的问题。我会要求他重写

这个 SQL 很复杂么?一个 leftjoin 就是个复杂的业务了?那你是没见过我司长达几百行的基础业务 SQL ,已经运行了好几年了,很稳定,可比你所谓的“把业务写在代码里”可读性强多了,维护起来也比又臭又长的代码方便。即使业务变更,前后对比 SQL 不比翻代码清晰?? OP 还在#34 楼喷别人干不过三年,我看你把复杂业务写成代码的你能干多少年。

看起来是权限表,除非你们用户非常的多..否则权限相关这点数据量 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
)
)
)

单单就这个 SQL 而言,不复杂,而且也没什么逻辑。
那种 ERP 和 OA 的项目里的 SQL ,才叫复杂

SQL 语句尽可能不要包含太多逻辑,数据层就干数据层的事,逻辑应该放在应用层,包含大量逻辑的 SQL 短期看省事,长期非常难以维护,慢慢就成了没人敢动的屎山。

楼上不少人说什么不够复杂的,显然是偏题

lz 是真的菜, 而且还是不接受意见的菜 🤧 自己在小公司干了几个月, 见到没学过的东西就说不合理, 咋滴, 公司是你开的? 在 v2 找不到同水平的菜鸡(好像找到了一个?)认可就破防了, 咋滴, v2 是你建的?

我个人觉着楼主发的例子还算可以,没有多复杂或者大量逻辑,如果楼主觉着复杂或者逻辑繁杂的话,求贴出来一个解决方案,就按照你发的例子,如果你写代码要怎么写,虚心求教,想看一下。

反对楼主的都是真心的? SQL 语句里写逻辑看你后面怎么维护,屎山都是不经意间堆起来的,等你发现兜不住了再转身,屎山已经把你淹没

菜狗。这种程度的都觉得可读性差,是你的问题。

写代码里怎么维护? SQL 代码也是代码,你能写在 Java 里维护,同样的逻辑写在 SQL 里就不会了么?

阿里那个什么 Java 规范里说连 JOIN 不得超过几个,是因为他们当时用的 MySQL ,对复杂 SQL 支持很差,多表连 JOIN 真的会搞死…但世间又不是只有 MySQL 这种残废。不说可读性、可维护性,只说性能,多表连 JOIN 根本不是 evil 。

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

逻辑写 SQL 里面最大的问题是需要进行缓存优化的时候,DB 已经是最后一层了,想优化都没办法。。。

业务逻辑丰富的 sql 可读性一般,调试困难,是我最不想碰的……
曾经见识过一个面向存储过程的 php 项目,项目里每个 sql 百行起步。业务增长越快,死得越快

正常!以前很多 java 的项目,后端用的是 oracle ,很多业务逻辑都是写在存储过程里面。那个调试才叫一个痛苦!
有些大的存储过程,能打两张 A3 纸!

还有统计类的 sql
大量用到 clickhouse 之类的内置函数

不知道为什么这么多楼同意把业务逻辑放在 SQL 里的,我个人是不赞同这种方式,增加维护难度和踩坑风险。不知道大家是技术栈不同的原因,还是因为什么。

这里单说 MySQL

我们项目(公司后台)里会联表查的只有搜索条件巨多遍布几个表以及要分页的情况
其他的逻辑都不会写 sql 里

啊啊啊?我赞同能跑就别乱动的观点,但可读性差这点还能有争论的?

还有把业务逻辑都封装在存储过程里的呢

最近读桥水基金创始人瑞·达利欧的《原则》,经历一次倒闭级的失败后,他的思维转变从“我知道我是对的”,到“我怎么知道我的是对的。”。
楼主显然还停留在“我知道我是对的,如果你们说我错了,那我也是对的”上面。

这还好吧,那种查询复杂的管理后台,都是多张表 left join 的,代码少,需求变更时改动也快。

要不看看我这 5 张表的 SQL
wuhao.pw/archives/107/

wuhao.pw/archives/277/
估计很多同仁看到这一堆的 SQL ,都要劝我,逻辑判断, 函数 ,存储过程 最好都别写到 sql 里
不过说实话,用了是真爽阿, 少写很多业务代码。
至于坑同事,或者后来者。
不至于坑,合适,不影响 sql 执行效率的逻辑判断, 函数 ,存储过程 带来极致的效率,如果这些特性都怕维护,而不用,那要这些特性干什么?存在即有其合理的地方。

这条 SQL 其实不算太难理解吧?排版也不错。而且代码可读性,其实是有指标的,比如说变量或者函数名的长度和命名,排版时用是否对齐这些。业务逻辑是否用 SQL 为什么会和可读性有关系呢?

看得很透彻!

我觉得这 SQL 也不是太复杂啊,LEFT JOIN 的那个子查询可写可不写,反正也注掉了。你说真正有逻辑的部分就只有 WHERE 的那个 in 了吧,这也不难啊。

稍微复杂点后台系统里,这种程度的 SQL 我们都是分给新人去开发测试的… 等你真看到的屎山一样十几张表揉在一起前前后后三四层左右结合内外连的时候再说吧… 而且一般这种屎山一样的 SQL ,换做程序实现更复杂…

两个有一个能跑就行(业界现状

pastebin.com/EKEh7veC

古典 ERP 里这种写法很多...

权限表这玩意完全没必要关联查。
1.数据量小,稍微有点要求的开发都会直接加载到内存
2.关联性弱,除了 user 和 role 的关联表数据量较大需要放到数据库查,其他的都可以直接走缓存查

综上所述你和楼主贴出来的 sql 都一般般

给楼主提个建议,要么跑,要么当 leader 禁止此类写法,否则都是打工的,没必要提这个,有心思写好代码的同事,你不说他也会改,没心思的你说了反而得罪人家,要么赶紧跑路

这算啥,我这一堆一二百行的 SQL ,需求整天变来变去,反反复复改了 N 次

能不能贴一下实现同样逻辑的代码

互联网公司和传统 IT 公司的做法本身就是不同的,场景不一样,互相觉得对方是傻 x 倒也很正常

你的示例,看起来问题不大

这个问题是数据库设计的问题了。这么多 join 是查什么呢?好奇。

以前看过有人吐槽教务系统的 sql ,鼠标滚轮滚坏了都拉不到底

楼主你这培训班水平就别来秀了

单词都看得懂,合在一起完全看不懂,即使有中文的注释

LZ 了解过存储过程吗?这个可能比较符合 “业务逻辑“ 写在 sql 里面的定义。
多表联查其实也不算什么业务逻辑。

要看贵公司做什么业务的。需要大量水平扩展的,放太多重计算任务在数据库侧确实不太合适;如果是做 ERP 这类需要强关系建模的,每个表不设外键,禁止 join ,就看会不会被公司打死。。

软件公司也不是只有 2c 这一种的。

遇到这种写法,我觉得最主要就提 3 个问题。

  1. 这么写以后团队里是否有复数人有能力修改。公交车因素是很重要的,如果团队里只有一个人有能力这么写,就不能这么写。
  2. 数据库是否需要横向扩展。应用服务器从 1 台变成 1000 台是比较容易的,数据库服务器从 1 台变成 2 台都比较难。这种结构能不能支撑以后的规模扩展?
  3. 自动化测试能不能保证。大家都知道,自动化测试可以大幅减少工作量,降低加班时间和炸锅几率。超长 SQL 能否用足够的测试去覆盖各种情况?如果不可以,那么拆分成应用层逻辑就是值得的。我觉得存储过程不是很大的问题,但是存储过程也应该可自动化测试才行。

所以这语法是啥玩意,标准 sql 语法里有这个吗?

看起来像是菜单权限的东西,这种数据量有限的东西,随便折腾的啊.
有一说一,程序员做的首要事情是让东西跑起来,其次才是需要考虑针对不同的情况进行处理。

这是什么妖风邪气啊

不单单是可读性差,主要在于水平扩展性差。不过如果你的服务 qps 不高,也不用太纠结。。。只是确实看着很捉急。

#89 java mybatis 😂

你特么傻逼 自己不会审题?老子放出来的就是个简单的示例。菜你妈了菜,大过年的逼我喷你!

我是菜鸟 想问这个 sql 哪里写了逻辑???哈哈哈

现在都流行低代码了, 我司已经把业务全部重构到 sql 里了, 压根不用写代码了, 改改 sql 就好了, 真爽

这个是根据用户查询菜单和角色吧。楼主你要是贴个 10 来次 left join 的 sql 这样估计更能说明问题,站你的人会更多

嚯,菜狗急了。

我说你丫才多少点见识啊,就搁那逼逼可读性。是不是你看不懂看着累的就叫可读性不好?你咋不去大街上随便拉个人过来评评你自己的代码,问问他能不能看懂呢?

还特么数据库限制用 join ?关系型数据库就是为 join 而生,你不用 join ,那你为什么不直接用文本文件?