MySQL内连接用于从同一个表中对父,子和子进行排序

时间:2013-08-06 16:47:22

标签: mysql join parent-child inner-join

MySQL数据库包含城镇内的国家,城镇和地区,所有这些都在“mailshot”表中。我想以降序粒度,使用和内连接的顺序返回整个集合。我实际上想向用户显示一个下拉列表,供他们选择城镇内的乡村或城镇或区域。

数据如下所示:

mailshot_id   mailshot_parent   mailshot_name   mailshot_level 
49              0               England         0
56              0               Scotland        0
140             49              London          1
149             49              York            1
191             56              Glasgow         1
300             140             Wimbledon       2
310             140             Westminster     2 
493             56              Edinburgh       1

我希望它输出如下:

mailshot_id   mailshot_parent   mailshot_name   mailshot_level 
49              0               England         0
149             49              York            1
140             49              London          1
300             140             Wimbledon       2
310             140             Westminster     2 
56              0               Scotland        0
191             56              Glasgow         1
493             56              Edinburgh       1


我几乎得到了这个:

 SELECT
    p.mailshot_id as p_id, 
    p.mailshot_name as p_name, 
    p.mailshot_level as p_level,
    p.mailshot_parent as p_parent, 
    c.mailshot_id as c_id, 
    c.mailshot_parent as c_parent, 
    c.mailshot_level as c_level, 
    c.mailshot_name as c_name, 
    case 
        WHEN p.mailshot_parent  = 0 THEN 
        p.mailshot_id 
        ELSE 
        p.mailshot_parent 
    END AS calcOrder 
FROM
    mailshot p LEFT JOIN mailshot c
    ON p.mailshot_id = c.mailshot_parent 
ORDER BY   calcOrder , p_id "

但是它没有将孙子记录(级别2)分组到子记录(级别1)附近我认为“案例”部分必须是错误的,我需要在mailshot_id和parent_id之间建立一些依赖于级别的关系。但我想不出来。

有什么建议吗?提前谢谢。

2 个答案:

答案 0 :(得分:1)

不幸的是,MySQL不支持层次结构查询(没有START WITH ... CONNECT BY或CTE等价物)。因此,你需要以艰难和丑陋的方式做到这一点。

以下内容适用于您的3个级别,如果您需要在树中更深入,则会非常麻烦。这是Fiddle

SELECT  C.MAILSHOT_ID
        ,C.MAILSHOT_PARENT
        ,C.MAILSHOT_NAME
        ,C.MAILSHOT_LEVEL
        ,CASE   WHEN C.MAILSHOT_LEVEL = 0 
                THEN CAST(C.MAILSHOT_ID AS CHAR(4))
                WHEN C.MAILSHOT_LEVEL = 1 
                THEN CONCAT(CAST(C.MAILSHOT_PARENT AS CHAR(4)),"..",CAST(C.MAILSHOT_ID AS CHAR(4)))
                ELSE CONCAT(CAST(P.MAILSHOT_PARENT AS CHAR(4)),"..",CAST(C.MAILSHOT_PARENT AS CHAR(4)),"..",CAST(C.MAILSHOT_ID AS CHAR(4)))
        END AS SORT_ORDER    
FROM    MAILSHOT C
LEFT OUTER JOIN
        MAILSHOT P
ON      P.MAILSHOT_ID = C.MAILSHOT_PARENT       
ORDER BY CASE   WHEN C.MAILSHOT_LEVEL = 0 
                THEN CAST(C.MAILSHOT_ID AS CHAR(4))
                WHEN C.MAILSHOT_LEVEL = 1 
                THEN CONCAT(CAST(C.MAILSHOT_PARENT AS CHAR(4)),"..",CAST(C.MAILSHOT_ID AS CHAR(4)))
                ELSE CONCAT(CAST(P.MAILSHOT_PARENT AS CHAR(4)),"..",CAST(C.MAILSHOT_PARENT AS CHAR(4)),"..",CAST(C.MAILSHOT_ID AS CHAR(4)))
        END

答案 1 :(得分:1)

这是分层表的一个典型示例,它更容易在oracle中查询,但这不是重点。 @Declan_K给了你一个很好的答案来实现你想要的。如果您正在寻找一种替代方案,通过组织良好的输出可以使您略有不同,您可以尝试这种方法:

SELECT m1.mailshot_name AS lev1n ,           
       m1.mailshot_id AS lev1,
       m1.mailshot_parent AS lev1p,
       m2.mailshot_name AS lev2n,
       m2.mailshot_id AS lev2,
       m2.mailshot_parent AS lev2p,
       m3.mailshot_name lev3n,
       m3.mailshot_id lev3,
       m3.mailshot_parent AS lev3p
FROM mailshot m1
LEFT JOIN mailshot m2 ON m2.mailshot_parent = m1.mailshot_id
LEFT JOIN mailshot m3 ON m3.mailshot_parent = m2.mailshot_id
WHERE m1.mailshot_parent = 0;

提供输出:

+----------+------+-------+-----------+------+-------+-------------+------+-------+
| lev1n    | lev1 | lev1p | lev2n     | lev2 | lev2p | lev3n       | lev3 | lev3p |
+----------+------+-------+-----------+------+-------+-------------+------+-------+
| England  |   49 |     0 | London    |  140 |    49 | Wimbledon   |  300 |   140 |
| England  |   49 |     0 | London    |  140 |    49 | Westminster |  310 |   140 |
| England  |   49 |     0 | York      |  149 |    49 | NULL        | NULL |  NULL |
| Scotland |   56 |     0 | Glasgow   |  191 |    56 | NULL        | NULL |  NULL |
| Scotland |   56 |     0 | Edinburgh |  493 |    56 | NULL        | NULL |  NULL |
+----------+------+-------+-----------+------+-------+-------------+------+-------+

关于如何处理MySQL中的分层数据的好总结可以在这里找到:
http://mikehillyer.com/articles/managing-hierarchical-data-in-mysql/
http://explainextended.com/2009/03/17/hierarchical-queries-in-mysql/