简体   繁体   中英

MySQL Select All Rows Linked By ID In Same Table

I have a table with the fields:

Parent references the primary key ID in the same table (not foreign key).

+----+--------+------------+
| ID | Parent |   Title    |
+----+--------+------------+
|  1 |      0 | Wallpapers |
|  2 |      1 | Nature     |
|  3 |      2 | Trees      |
|  4 |      3 | Leaves     |
+----+--------+------------+

I'm trying to select a row and all its parents. For example if I select "Leaves" I want to get "Trees", "Nature", and "Wallpaper" as well since that is the parent path up the hierarchy. Is this possible in one query? At the moment I'm using a loop in ColdFusion to get the next parent each iteration but it's not efficient enough.

You have to use a self join to achieve this:-

 SELECT T1.Title AS CHILD, T2.Title AS PARENT
 FROM YOUR_TABLE T1, YOUR_TABLE T2
 WHERE T1.PARENT = T2.ID
 AND T1.Title = 'Leaves'

In PHP, I wrote a function that retrieve all the hierarchy of my route table (infinite depth).

I think that, in this example, you can see SQL syntax of query you are looking for . I use same column names except in lowercase.

function get_breadcrumb($route_id) {
    
    //access PDO mysql object instance
    global $db;

    // sanitize route ID
    $route_id = intval($route_id);
    
    // query construction
    $q = "SELECT T2.*
            FROM (
                SELECT
                    @r AS parent_id,
                    (SELECT @r := `parent` FROM `route` WHERE id = parent_id) AS `parent`,
                    @l := @l + 1 AS `depth`
                FROM
                    (SELECT @r := $route_id, @l := 0) vars,
                    `route` T3
                WHERE @r <> 0) T1
            JOIN `route` T2
                ON T1.parent_id = T2.id
            ORDER BY T1.`depth` DESC";
    
    // call query in database
    if($res = $db->query($q)) {
        if($res = $res->fetchAll(PDO::FETCH_ASSOC)) {
            if($size = sizeof($res) > 0) { 
                
                // push results in breadcrumb items array
                $breadcrumb['items']  = $res;
                $breadcrumb['levels'] = $size;
                
                // retrieve only titles
                $titles = array_column($res, 'title');

                // construct html result seperated by '>' or '/'
                $breadcrumb['html']['gt'] = implode(' > ', $titles);
                $breadcrumb['html']['sl'] = implode(' / ', $titles);

                // returns all result (added in SESSION too)
                return $_SESSION['app']['breadcrumb'] = $breadcrumb;
            }
        }
    }
    
    // no result for that route ID
    return false;
}

Try this

SELECT 
      DISTINCT c.id AS 'ID', c.title AS 'Name'
FROM YourTable c, YourTable p 
WHERE c.id = p.parent AND c.title = 'Leaves'

Use a UNION to combine the query that returns the main row with another query that returns the parent row.

SELECT *
FROM YourTable
WHERE Title = "Leaves"
UNION
SELECT t1.*
FROM YourTable AS t1
JOIN YourTable AS t2 ON t1.id = t2.parent
WHERE t2.Title = "Leaves")

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM