新手求指教,查询一对多/多对多关系,映射到编程语言的对象,常规操作是怎样的? - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
MySQL 5.5 Community Server
MySQL 5.6 Community Server
Percona Configuration Wizard
XtraBackup 搭建主从复制
Great Sites on MySQL
Percona
MySQL Performance Blog
Severalnines
推荐管理工具
Sequel Pro
phpMyAdmin
推荐书目
MySQL Cookbook
MySQL 相关项目
MariaDB
Drizzle
参考文档
http://mysql-python.sourceforge.net/MySQLdb.html
changrui0608
V2EX    MySQL

新手求指教,查询一对多/多对多关系,映射到编程语言的对象,常规操作是怎样的?

  •  
  •   changrui0608 2018-06-14 15:06:41 +08:00 3946 次点击
    这是一个创建于 2752 天前的主题,其中的信息可能已经有所发展或是发生改变。
    比如最简单的模型吧,博客有文章 post 和标签 tag,是多对多关系;
    数据库 schema 设计中,一般通过 id 的互相引用;
    编程语言中,通常表现为一个 Post 对象,有一个 Tags 数组属性,里边是多个 Tag 的内容;

    问题就是,不用 ORM 纯手写 SQL 的话,怎么做到一次查询数据库,转换到 Post 对象,并填充 Tags 属性的?

    看过一些 ORM 的实际 SQL 日志,一般会是用 LEFT JOIN,但 LEFT JOIN 的话,比如一个 Post 有多个 Tag,那么查询结果中一个含有 N 个 Tag 的 Post 就会重复出现 N 次。

    虽然是可以手动编程排除重复 Post 并依次处理 Tag,但是感觉极为蛋疼,复杂度也不低,所以想请教下,这种情况下的常规操作是怎样的?
    9 条回复    2018-06-15 08:48:18 +08:00
    alexsunxl
        1
    alexsunxl  
       2018-06-14 16:14:27 +08:00
    典型的想得太多, 做得太少, 哈哈哈
    别纠结这些了, 最后还是看场景看业务看历史
    这种东西没有最佳实践的,只能说相对较合适,
    至于怎么是合适,那还是多积累吧
    changrui0608
        2
    changrui0608  
    OP
       2018-06-14 16:28:07 +08:00
    @alexsunxl
    兄弟,我不是做的太少,我是做到这儿了不知道怎么办才来问的,你这话就和没说一样啊...
    infreboot
        3
    infreboot  
       2018-06-14 17:01:19 +08:00
    你可以换种方式,多查几次。别想着一条 SQL 查出来。。以前我也是想一条查出来,结果发现是为难自己
    DavidNineRoc
        4
    DavidNineRoc  
       2018-06-14 17:25:55 +08:00   1
    看了一下 lv 的 SQL

    ## 先查询 posts 表
    select * from posts where xxx
    ## 连接查询关联关系
    SELECT
    `tags`.*,
    `post_tag`.`post_id` AS `pivot_post_id`,
    `post_tag`.`tag_id` AS `pivot_tag_id`
    FROM
    `tags`
    INNER JOIN `post_tag` ON `tags`.`id` = `post_tag`.`tag_id`
    WHERE
    `post_tag`.`post_id` IN (## 这里是 posts 表查询的数据 ## )
    ##
    然后将第二次查询的数据按照 pivot_post_id 分组,循环一遍 posts 查询出的数据,直接按 pivot_post_id 组设置为单个 posts 的属性。
    AlphaTr
        5
    AlphaTr  
       2018-06-14 17:41:41 +08:00
    关系型数据库一次查询返回就会出现「 N 个 Tag 的 Post 就会重复出现 N 次」这种情况。一种方式就是你说的,手动编程排重;另一种方式就是多次查询。或者可以直接上非关系型数据库;
    changrui0608
        6
    changrui0608  
    OP
       2018-06-14 18:13:33 +08:00
    @DavidNineRoc 多谢,查了一下午似乎是这种方法最合适,顺便 lv 全程是什么
    cxbig
        7
    cxbig  
       2018-06-14 18:17:39 +08:00 via iPhone
    关键词:ORM eager loading
    抓 SQL 看看人家怎么处理的就明白了
    Foolt
        8
    Foolt  
       2018-06-14 18:17:50 +08:00
    MySQL 去重关键字 DISTINCT 了解一下
    DavidNineRoc
        9
    DavidNineRoc  
       2018-06-15 08:48:18 +08:00
    @changrui0608 laravel
    关于     帮助文档     自助推广系统     博客     API     FAQ     Solana     2631 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 27ms UTC 12:10 PVG 20:10 LAX 04:10 JFK 07:10
    Do have faith in what you're doing.
    ubao msn snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86