1

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

数据如下所示:

mailshot_id mailshot_parent mailshot_name mailshot_level
49 0英格兰0
56 0 苏格兰 0
140 49 伦敦 1
149 49 约克 1
191 56 格拉斯哥 1
300 140 温布尔登 2
310 140 威斯敏斯特 2
493 56 爱丁堡 1

我希望它像这样输出:

mailshot_id mailshot_parent mailshot_name mailshot_level
49 0英格兰0
149 49 约克 1
140 49 伦敦 1
300 140 温布尔登 2
310 140 威斯敏斯特 2
56 0 苏格兰 0
191 56 格拉斯哥 1
493 56 爱丁堡 1


我几乎得到了它:

选择
    p.mailshot_id 作为 p_id,
    p.mailshot_name 作为 p_name,
    p.mailshot_level 作为 p_level,
    p.mailshot_parent 作为 p_parent,
    c.mailshot_id 作为 c_id,
    c.mailshot_parent 作为 c_parent,
    c.mailshot_level 作为 c_level,
    c.mailshot_name 作为 c_name,
    案子
        当 p.mailshot_parent = 0 那么
        p.mailshot_id
        别的
        p.mailshot_parent
    结束为 calcOrder
从
    mailshot p LEFT JOIN mailshot c
    ON p.mailshot_id = c.mailshot_parent
ORDER BY calcOrder , p_id "

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

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

4

2 回答 2

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/分层查询在 mysql/

于 2013-08-06T18:36:49.133 回答
1

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

以下将适用于您的 3 个级别,但如果您需要在树中获得更多深度,则会变得非常麻烦。这是小提琴

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
于 2013-08-06T18:19:40.877 回答