mysql 查询问题-一个表多次 join 自己,可以做到每个表返回一行记录么 - 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
Yuicon
V2EX    MySQL

mysql 查询问题-一个表多次 join 自己,可以做到每个表返回一行记录么

  •  
  •   Yuicon
    Yuicon 2019-06-28 11:17:53 +08:00 5624 次点击
    这是一个创建于 2305 天前的主题,其中的信息可能已经有所发展或是发生改变。

    比如这样的查询:

    SELECT * FROM sys_address three LEFT JOIN sys_address two ON three.parent_code = two.code LEFT JOIN sys_address o ON two.parent_code = o.code WHERE three.CODE = 110101 

    返回是这样的:

    "110101" "东城区" "110100" "3" "110100" "市辖区" "110000" "2" "110000" "北京市" "" "1" 

    有办法做到返回这样的结构么:

    "110101" "东城区" "110100" "3" "110100" "市辖区" "110000" "2" "110000" "北京市" "" "1" 
    22 条回复    2019-06-29 08:56:53 +08:00
    Yuicon
        1
    Yuicon  
    OP
       2019-06-28 11:21:58 +08:00
    我自己倒是想到一种办法 就是有点蛋疼 非常长
    Yuicon
        2
    Yuicon  
    OP
       2019-06-28 11:22:23 +08:00
    ```
    SELECT three.*
    FROM cdshopping.sys_address three
    WHERE three.CODE = 110101 UNION

    SELECT two.*
    FROM cdshopping.sys_address three
    LEFT JOIN cdshopping.sys_address two ON three.parent_code = two.code
    WHERE three.CODE = 110101 UNION

    SELECT o.*
    FROM cdshopping.sys_address three
    LEFT JOIN cdshopping.sys_address two ON three.parent_code = two.code
    LEFT JOIN cdshopping.sys_address o ON two.parent_code = o.code
    WHERE three.CODE = 110101
    ```
    Gatsbywl
        3
    Gatsbywl  
       2019-06-28 12:22:17 +08:00
    SELECT * FROM sys_address
    WHERE CODE IN (
    -- 3 级地名的 code
    110101,
    -- 选择上一步的 parent_code
    (SELECT three.parent_code
    FROM testdb.sys_address three
    WHERE three.CODE = 110101),
    -- 继续选择上一步的 parent_code,
    (SELECT parent_code FROM sys_address
    WHERE CODE =
    (SELECT three.parent_code
    FROM testdb.sys_address three
    WHERE three.CODE = 110101))
    -- 如果还有需求选择 再上一级的'中国',重复上一个步骤即可
    )
    Gatsbywl
        4
    Gatsbywl  
       2019-06-28 12:26:07 +08:00   1
    我暂时只能想到这种思路,其实就是根据最低级区域的 代号 往上寻根,所以每次
    WHERE code = 上一步的 parent_code
    reus
        5
    reus  
       2019-06-28 12:26:21 +08:00
    用 PostgreSQL 或者 MySQL 8 的 recursive CTE
    Yuicon
        6
    Yuicon  
    OP
       2019-06-28 12:41:34 +08:00
    @Gatsbywl 看来是不存在方便的方案了 这种需求估计也少
    meetocean
        7
    meetocean  
       2019-06-28 13:01:33 +08:00   1
    亲自测试可用:

    (
    SELECT
    three.id as id3, three.title title3
    FROM plots three
    LEFT JOIN plots two ON three.parent_id = two.id
    LEFT JOIN plots one ON two.parent_id = one.id
    WHERE three.id = 7
    )
    UNION
    (
    SELECT
    two.id as id2, two.title title2
    FROM plots three
    LEFT JOIN plots two ON three.parent_id = two.id
    LEFT JOIN plots one ON two.parent_id = one.id
    WHERE three.id = 7
    )
    UNION
    (
    SELECT
    one.id as id1, one.title title1
    FROM plots three
    LEFT JOIN plots two ON three.parent_id = two.id
    LEFT JOIN plots one ON two.parent_id = one.id
    WHERE three.id = 7
    )


    按照这个思路,把 SQL 修改一下即可。
    meetocean
        8
    meetocean  
       2019-06-28 13:11:07 +08:00
    这是硬查询,如果你不需要数据库里的三行,而是三行字符串,那么还有方法,重组字符串。
    JQZhang
        9
    JQZhang  
       2019-06-28 13:20:32 +08:00   1
    还是喜欢 Oracle 的 connect by,你可以搜一下 mysql 仿写的 connect by
    Yuicon
        10
    Yuicon  
    OP
       2019-06-28 13:38:39 +08:00
    @meetocean 兄弟思路一样啊
    Yuicon
        11
    Yuicon  
    OP
       2019-06-28 13:40:25 +08:00
    @JQZhang 看了下好像要写函数的 不怎么适合
    Alexisused
        12
    Alexisused  
       2019-06-28 13:53:13 +08:00
    意义在哪里?
    whl619969187
        13
    whl619969187  
       2019-06-28 16:22:18 +08:00
    就是递归查询嘛,mysql 8 好像支持 oracle 支持 其他没用过
    1ffree
        14
    1ffree  
       2019-06-28 16:32:07 +08:00
    说明表设计有问题。
    要么做个冗余, 要么多行取出来内存里做处理
    oaix
        15
    oaix  
       2019-06-28 16:49:54 +08:00
    code 看起来有编码规范,所以只要 where code in ('110101', '110100', '110000')
    Yuicon
        16
    Yuicon  
    OP
       2019-06-28 17:08:41 +08:00
    @Alexisused ......
    因为这实际是三条记录我当然希望返回的三个对象
    Yuicon
        17
    Yuicon  
    OP
       2019-06-28 17:09:42 +08:00
    @1ffree 怪过去也没用 人都走了 现在写的是我才是现实
    meetocean
        18
    meetocean  
       2019-06-28 17:10:00 +08:00
    @oaix
    从楼主的题目,可推断数据表是层级表,并且只有三级,分别是省、市、区。
    用户给定的查询条件就是给定叶子结点(没有子节点的节点)的一个具体值“ 110000 ”。
    根据这个条件得到上级(市)与上上级(省)数据。
    Yuicon
        19
    Yuicon  
    OP
       2019-06-28 17:12:33 +08:00
    @whl619969187 比起引入存储过程或者自定义函数我宁愿查三次。。。
    Yuicon
        20
    Yuicon  
    OP
       2019-06-28 17:14:50 +08:00
    @meetocean 我觉得他是个天才 把复杂度转移到业务层去了 可惜这种药一开始就约定好
    saulshao
        21
    saulshao  
       2019-06-28 17:55:18 +08:00
    这个建议是要多次查询这个表,不建议完全用 SQL.
    Takamine
        22
    Takamine  
       2019-06-29 08:56:53 +08:00
    第一,我不会这么写;
    第二,我不会这么写。:doge:
    第三,作为 CRUDboy 我会把这个放到业务层。
    关于     帮助文档     自助推广系统     博客     API     FAQ     Solana     2212 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 27ms UTC 16:02 PVG 00:02 LAX 09:02 JFK 12:02
    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