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 · 3313 次点击
    这是一个创建于 2338 天前的主题,其中的信息可能已经有所发展或是发生改变。
    比如最简单的模型吧,博客有文章 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
    兄弟,我不是做的太少,我是做到这儿了不知道怎么办才来问的,你这话就和没说一样啊...
    Stevenv
        3
    Stevenv  
       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 xxxx
    ## 连接查询关联关系
    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   ·   实用小工具   ·   5582 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 26ms · UTC 03:32 · PVG 11:32 · LAX 19:32 · JFK 22:32
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.