How to show parent terms in view for restricted nodes categorised with child term?
In case anyone has the same issue, I gave up in the end and wrote a custom module since I find views a pain in the ass.

My module uses nested queries which is embarassing, but it's still fast to run (unless you have a massive list of taxononomy terms) so it doesn't matter too much for this purposes.

The module outputs a Drupal block, the content of which comes from this function:

function list_of_resource_tags(){

// Retrieve the logged in user
global $user;

// Select all "Metadata" terms for the nodes the logged in user
// has permission to see    
$sql_terms = '
SELECT DISTINCT(term_data.tid) AS term_id, term_data.name, term_hierarchy.parent, term_data.weight
FROM node_access 
INNER JOIN node ON node_access.nid = node.nid 
INNER JOIN term_node ON node.nid = term_node.nid
INNER JOIN term_data ON term_node.tid = term_data.tid
INNER JOIN term_hierarchy ON term_data.tid = term_hierarchy.tid
WHERE node_access.grant_view = 1 
AND node.status = 1 /* Published nodes */
AND term_data.vid = 9 /* Taxonomy terms of "Metadata" vocabulary only */
AND node_access.gid IN (SELECT rid AS roles FROM users_roles WHERE uid = %d) /* Logged-in user is granted permission to these nodes */
ORDER BY term_data.weight';

$result_terms = db_query($sql_terms, $user-&gt;uid);

$displayed_terms = array();
$output = '';
while ($row = db_fetch_object($result_terms)) {
    // If tag is top-level, just display and put in array
    if ($row-&gt;parent == 0 &amp;&amp; in_array($row-&gt;term_id, $displayed_terms) == FALSE){
        $output .= '&lt;div class="views-row"&gt;&lt;a href="taxonomy/term/'.$row-&gt;term_id.'"&gt;'.$row-&gt;name.'&lt;/a&gt;&lt;/div&gt;';
        $displayed_terms[] = $row-&gt;term_id;
    } 
    // Test if we've already displayed the tags parent, if not, retrieve it
    else if (in_array($row-&gt;parent, $displayed_terms) == FALSE){
        $sql_parent = '
        SELECT *
        FROM term_data
        WHERE tid = %d';

        $result_parent = db_query($sql_parent, $row-&gt;parent);
        $row_parent = db_fetch_object($result_parent);

        $output .= '&lt;div class="views-row"&gt;&lt;a href="taxonomy/term/'.$row_parent-&gt;tid.'"&gt;'.$row_parent-&gt;name.'&lt;/div&gt;';
        $displayed_terms[] = $row_parent-&gt;tid;          
    }
}

return $output;
}