老生常谈 关于 子查询的应用

wuhao1 · 2024-9-23 10:32:22 · 111 次点击
select uid,(select wechat from member_a  where tuid=m.tuid)wechat,
(select name from admin_user where id =(select opuid from link where id=ldid))fzr
,no,ctime,(select ctime from member where id=uid)uctime,
ldid,adid,rmb,(select count(id) from money_o where uid=m.uid and ctime < m.ctime)readin,
(select count(id) from money_o where uid=m.uid and ctime > m.ctime)readout
from money m where  
ldid in(select id from link where qd=666 and ctime>$tms) and
status=1 and ctime>=$czs having ctime> uctime and (ctime-uctime<480);

在后端程序中少不了要和 sql 接触,一部分人对子查询很抗拒认为 把很多逻辑都隐藏到 sql 中了不利于程序的可读性,然而 你同意吗?  
上述 sql 使用了很多子查询,查询效率也并不会低,不过肯定可以省很多代码,因为很多数据如果不用子查询,那么就要多次链接数据库去做查询,然后组合数据。  
愚见:适当的使用子查询其实是会更高效的!
举报· 111 次点击
登录 注册 站外分享
10 条回复  
WashFreshFresh 小成 2024-9-23 14:11:22
用 jpa 的时候基本都是单表查询,用 mybatis 的时候为了偷懒少写 sql 就 sql 一把梭了,因为不想写多个 xml ;我的体验是,sql 写的少代码写的多除了增强代码可读性,还能增强记忆,业务会记得比较清楚; sql 一把梭的真的今天写完明天就忘记业务细节了。
ldx78203199 小成 2024-9-23 14:12:55
业务上谁写这种 sql ,直接开喷, 优化+维护成本太高,如果业务场景真有这么高建议上 ES
liangdi 小成 2024-9-23 14:15:47
我一直做 toB 的系统,所以肯定是代码逻辑优先,基本不会这么用,要么是 db 自己做视图
sagaxu 初学 2024-9-23 14:16:24
管理后台读从库,子查询,多表连随便造。但在非管理后台,使用较复杂的子查询或多表相连,有两个很纠结的点

1. 缓存机制不好设计,复杂程度远超单表查询
2. DB 采样统计失真,查询计划选择了错误的索引可能炸库
encounter2017 小成 2024-9-23 14:28:41
我觉得还是看业务场景,比如说我这里有一个业务场景就是需要查询树状结点下面的所有子节点信息,这种情况下用 recursive cte 查询就很方便,一次就能查完,IO 都在数据库做了,不然的话还得多次查询数据库.

一个简单的示例
```
CREATE TABLE binary_tree (
    id INT PRIMARY KEY,
    value VARCHAR(255),
    parent_id INT,
    FOREIGN KEY (parent_id) REFERENCES binary_tree(id)
);

INSERT INTO binary_tree (id, value, parent_id) VALUES
(1, 'Root', NULL),
(2, 'Left Child', 1),
(3, 'Right Child', 1),
(4, 'Left Grandchild', 2),
(5, 'Right Grandchild', 2),
(6, 'Another Left Grandchild', 3),
(7, 'Another Right Grandchild', 3);

WITH RECURSIVE tree_cte AS (
    -- Base case: select the root node
    SELECT id, value, parent_id, 0 AS level, CAST(id AS text) AS path
    FROM binary_tree
    WHERE parent_id IS NULL

    UNION ALL

    -- Recursive case: select child nodes
    SELECT c.id, c.value, c.parent_id, p.level + 1, CONCAT(p.path, ',', CAST(c.id AS text))
    FROM binary_tree c
    JOIN tree_cte p ON c.parent_id = p.id
)
SELECT id, value, parent_id, level, path
FROM tree_cte
ORDER BY path;

1,Root,,0,1
2,Left Child,1,1,"1,2"
4,Left Grandchild,2,2,"1,2,4"
5,Right Grandchild,2,2,"1,2,5"
3,Right Child,1,1,"1,3"
6,Another Left Grandchild,3,2,"1,3,6"
7,Another Right Grandchild,3,2,"1,3,7"

```
WIN2333 小成 2024-9-23 14:43:16
这种确实适合代码逻辑,因为一眼就知道干了啥,sql 有心智负担。更值得讨论的是 join ,总有人跳出来说 join 怎么怎么不好,巴拉巴拉,有些一条 sql join 一下干出来的非得用代码实现。。。。
cccvno1 小成 2024-9-23 15:08:30
任何一个子查询的表数据出了问题,这个查询直接就废了
8355 小成 2024-9-23 15:55:43
只能接受 where 条件用子查询,类似 in 的范围比较大或者查询条件在子查询表中。
这种 sql 完全无法优化,部分小表或着纯粹的关联查询在数据组装中批量查询可以直接读缓存,这么看起来真的是糟糕的不得了。。。
ZZ74 小成 2024-9-23 16:07:54
我无所谓
SQL 也是一种编程语言,大部分场景下 可以用 sql (存储过程),也可以用常见的编程语言+sql 实现。效率上也没多大区别。
12下一页
返回顶部