求一个高效的SQL语句。

求一个高效的SQL语句。

风苍溪 发布于 2021-11-26 字数 348 浏览 770 回复 21

数据库是PG9

两张表,A表:

列名:id,name

1,张三

2,李四

B表:

列名:s_id,t_id

1,1,2

2,2,1

B表的s_id和t_id对应A表的ID。想求一条高效的SQL来查询B表,显示出s_id和t_id对应的那么。比如按照现在B表的数据,显示出来应该是第一行:张三,李四。第二行:李四,张三。

如果你对这篇文章有疑问,欢迎到本站 社区 发帖提问或使用手Q扫描下方二维码加群参与讨论,获取更多帮助。

扫码加入群聊

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(21

毁梦 2021-12-01 21 楼

我不明白,LZ如果想把所有数据都查出来,几百万对几百万,怎么加索引都快不了,只有sort merge join合适这种大批量的表连接。但是这样做的使用场景是什么,除了“导出所有消息”这种,想不到还有什么用处?

如果只是查某个用户的信息等不,请LZ把问题场景再详细点说明才行。

野心澎湃 2021-12-01 20 楼
SELECT t.name n1, a.name n2 FROM (
 SELECT a.name, t_id  FROM b
  INNER JOIN a ON a.id = b.s_id
 ) t INNER JOIN a ON a.id = t.t_id

这是用dz测试的代码

SELECT t.*, m.username from (select t.tid, m.username, t.authorid, m.uid, t.dateline from cdb_threads t 
  INNER JOIN cdb_members m on m.uid = t.authorid ORDER BY t.dateline DESC LIMIT 15) t  
INNER JOIN cdb_members m on m.uid = t.authorid
ORDER BY t.dateline DESC LIMIT 15;

查询计划:

Limit  (cost=66212.46..66249.95 rows=15 width=40)
  ->  Nested Loop  (cost=66212.46..66249.95 rows=15 width=40)
        ->  Limit  (cost=66212.46..66212.50 rows=15 width=28)
              ->  Sort  (cost=66212.46..67284.65 rows=428876 width=28)
                    Sort Key: t.dateline
                    ->  Merge Join  (cost=65.52..55690.23 rows=428876 width=28)
                          Merge Cond: (m.uid = t.authorid)
                          ->  Index Scan using cdb_members_pkey on cdb_members m  (cost=0.00..18690.79 rows=209764 width=16)
                          ->  Index Scan using "threads.authorid" on cdb_threads t  (cost=0.00..31114.72 rows=428876 width=12)
        ->  Index Scan using cdb_members_pkey on cdb_members m  (cost=0.00..2.47 rows=1 width=16)
              Index Cond: (uid = t.authorid)
时间: 0.131s

緦唸λ蓇 2021-12-01 19 楼

而且根据业务,确实是需要显示出来发件人和收件人的。 你这个表相当简单,你要是再加一个字段,保存收件人,你就会遇见我问的问题了。

各自安好 2021-12-01 18 楼

然后你说道array存储,这个完全没问题,我用的也是PG,PG9.4的。可是还是没有解决高效对应ID和昵称的问题。

妖妓 2021-12-01 17 楼

回复
如果是要显示id对应的名字,要么直接保存这个名字,问题是当id对应的名字变化后保存的名字不会自动更新。或者把这个字段展开为一个表,每行保存一条对应记录,然后关联到id名字表上吧

陌若浮生 2021-12-01 16 楼

回复
你的第一个是肯定不行的。后面那个方法,也不见得是好的方法。

疾风者 2021-12-01 15 楼

回复
pmreluid保存有收件人的呀。authorid字段是发件人

怎言笑 2021-12-01 14 楼

@梅公子 原来是消息表,你可以参考discuz的uc这个库设计。相关的pm_indexs, pm_lists 这两张表。

因为我把dz数据库换成了pgsql,所以采用了array方式来保存uid关系,见下图 pmreluid。原字段是类似你设计的'1,2'这样的字符串,改为array之后索引更高效,并且可以索引查询数组中单个值

 

月牙弯弯 2021-12-01 13 楼

你这设计有点炸 感觉像是好友/关注这类的列表

同意楼上说的 这设计怎么优化估计都难

写个函数把t_id的值给它转换一下然后用in试试

最后把查出来的东西放缓存里 异步小批量更新

等你爱我 2021-12-01 12 楼

回复
现在不就是想找更快的方法解决id对应名字的问题么?表里面存的一样只是id。

无人问我粥可暖 2021-12-01 11 楼

回复
我那表里面不就只有两个字段么?哪里来的第三个字段。

想挽留 2021-12-01 10 楼

回复
1,1,2

空城仅有旧梦在 2021-12-01 9 楼

回复
最前面的1和2表示行数。。。。

各自安好 2021-12-01 8 楼

回复
晕。。。

柳若烟 2021-12-01 7 楼

lz t_id字段保存的是如 "1,2" 这样的字符串??

表结构设计有问题,再怎么优化SQL都没有

只为守护你 2021-12-01 6 楼

应该是内连接的效率高一点吧

归途 2021-12-01 5 楼

这两条sql你对比一下看那个性能高一点

韬韬不绝 2021-12-01 4 楼

这个方法可以,但如果两张表里面有上百万记录的话,效率不会很理想。

成熟的代价 2021-11-30 3 楼

回复
怎样才算理想

混吃等死 2021-11-28 2 楼
select a.name,aa.name from b b 
inner join a a 
on b.s_id = a.id
inner join a aa
on b.t_id = aa.id

三月梨花 2021-11-28 1 楼
select a.id,
(select b.name from b b where b.s_id=a.id) sname ,
(select bb.name from b bb where bb.t_id = a.id) tname
from a a ;