逻辑大量的写在 sql 语句里

2022-02-21 16:40:54 +08:00
 moxiaowei

今天看了下同事写的代码,才发现他居然喜欢把大量的逻辑写在 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 的也很多。
17405 次点击
所在节点    Java
244 条回复
Baloneo
2022-02-21 19:13:22 +08:00
```
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
```
whoisjohnlee
2022-02-21 19:28:02 +08:00
逻辑写 SQL 里面最大的问题是需要进行缓存优化的时候,DB 已经是最后一层了,想优化都没办法。。。
benzalus
2022-02-21 19:33:27 +08:00
业务逻辑丰富的 sql 可读性一般,调试困难,是我最不想碰的……
曾经见识过一个面向存储过程的 php 项目,项目里每个 sql 百行起步。业务增长越快,死得越快
ytmsdy
2022-02-21 19:47:27 +08:00
正常!以前很多 java 的项目,后端用的是 oracle ,很多业务逻辑都是写在存储过程里面。那个调试才叫一个痛苦!
有些大的存储过程,能打两张 A3 纸!
Leviathann
2022-02-21 19:48:22 +08:00
还有统计类的 sql
大量用到 clickhouse 之类的内置函数
jellywong
2022-02-21 19:48:40 +08:00
不知道为什么这么多楼同意把业务逻辑放在 SQL 里的,我个人是不赞同这种方式,增加维护难度和踩坑风险。不知道大家是技术栈不同的原因,还是因为什么。
jellywong
2022-02-21 19:49:50 +08:00
@jellywong 这里单说 MySQL
Leviathann
2022-02-21 19:54:11 +08:00
我们项目(公司后台)里会联表查的只有搜索条件巨多遍布几个表以及要分页的情况
其他的逻辑都不会写 sql 里
dcsuibian
2022-02-21 20:05:30 +08:00
啊啊啊?我赞同能跑就别乱动的观点,但可读性差这点还能有争论的?
idblife
2022-02-21 20:07:55 +08:00
还有把业务逻辑都封装在存储过程里的呢
wonderfulcxm
2022-02-21 20:19:31 +08:00
最近读桥水基金创始人瑞·达利欧的《原则》,经历一次倒闭级的失败后,他的思维转变从“我知道我是对的”,到“我怎么知道我的是对的。”。
楼主显然还停留在“我知道我是对的,如果你们说我错了,那我也是对的”上面。
notejava
2022-02-21 20:41:57 +08:00
这还好吧,那种查询复杂的管理后台,都是多张表 left join 的,代码少,需求变更时改动也快。
onhao
2022-02-21 20:55:31 +08:00
要不看看我这 5 张表的 SQL
https://wuhao.pw/archives/107/

https://wuhao.pw/archives/277/
估计很多同仁看到这一堆的 SQL ,都要劝我,逻辑判断, 函数 ,存储过程 最好都别写到 sql 里
不过说实话,用了是真爽阿, 少写很多业务代码。
至于坑同事,或者后来者。
不至于坑,合适,不影响 sql 执行效率的逻辑判断, 函数 ,存储过程 带来极致的效率,如果这些特性都怕维护,而不用,那要这些特性干什么?存在即有其合理的地方。
gengchun
2022-02-21 21:25:29 +08:00
这条 SQL 其实不算太难理解吧?排版也不错。而且代码可读性,其实是有指标的,比如说变量或者函数名的长度和命名,排版时用是否对齐这些。业务逻辑是否用 SQL 为什么会和可读性有关系呢?
sadhen
2022-02-21 21:31:05 +08:00
@est 看得很透彻!
c6h6benzene
2022-02-21 21:38:47 +08:00
我觉得这 SQL 也不是太复杂啊,LEFT JOIN 的那个子查询可写可不写,反正也注掉了。你说真正有逻辑的部分就只有 WHERE 的那个 in 了吧,这也不难啊。
xy90321
2022-02-21 22:12:00 +08:00
稍微复杂点后台系统里,这种程度的 SQL 我们都是分给新人去开发测试的… 等你真看到的屎山一样十几张表揉在一起前前后后三四层左右结合内外连的时候再说吧… 而且一般这种屎山一样的 SQL ,换做程序实现更复杂…
Cbdy
2022-02-21 22:32:10 +08:00
两个有一个能跑就行(业界现状
vibbow
2022-02-21 22:45:38 +08:00
https://pastebin.com/EKEh7veC

古典 ERP 里这种写法很多...
night98
2022-02-21 22:46:46 +08:00
@ikas 权限表这玩意完全没必要关联查。
1.数据量小,稍微有点要求的开发都会直接加载到内存
2.关联性弱,除了 user 和 role 的关联表数据量较大需要放到数据库查,其他的都可以直接走缓存查

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

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/835439

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX