Frage

I'm designing a tag-based pseudo-category system.

There I have two tables - connection and keyword. 'keyword' defines categories and 'connection' is an adjacency list.

When a category is clicked, the view shows subcategories.

SELECT kw.kw_id, kw.kw_name, kw.kw_desc
FROM keyword AS kw, connection AS conn
WHERE conn.kw1id = :kw1 AND conn.kw2id = kw.kw_id

This works just fine, but now I want to sort those subcategories by the number of their children.

SELECT  child.id AS child_id, keyword.kw_name AS child_name, keyword.kw_desc AS child_desc,
            COUNT(r1.conn_id) AS out_degree
FROM keyword
INNER JOIN connection AS r1 ON r1.kw1id = keyword.kw_id
INNER JOIN (
    SELECT kw2id AS id
    FROM connection AS conn
    WHERE conn.kw1id = [ID_CLICKED]
) AS child ON child.id = r1.kw1id

GROUP BY r1.kw1id

ORDER BY out_degree DESC

But this returns only categories with >0 children. How do I include leaf nodes?

War es hilfreich?

Lösung

simply replace the INNER with LEFT ought to do it...

by the way you don't really need that subquery

its hard to be sure, but from your description I think something like this is what you want??

 SELECT  k.id AS child_id,   
         k.kw_name AS child_name,  
         k.kw_desc AS child_desc,
         COUNT(rb.conn_id) AS out_degree
 FROM connection AS ra 
 LEFT JOIN keyword As k ON ra.kw2id = k.id AND ra.reltype = 'blah'
 LEFT JOIN connection As rb ON rb.kw1id = k.id AND rb.reltype = 'blah'
 WHERE ra.kw1id = [ID_CLICKED]
 GROUP BY k.id 
 ORDER BY out_degree DESC

This should count the children of the children of [ID_CLICKED] and should still include the childless

To avoid multiple counting, change this:

COUNT(rb.conn_id) AS out_degree

to

COUNT(distinct rb.kw2id) AS out_degree

so each grand child only gets counted once

Andere Tipps

as something closer to your original query - does this work? (note the 3 changes)

SELECT  child.id AS child_id, keyword.kw_name AS child_name, keyword.kw_desc AS child_desc,
            COUNT(r1.conn_id) AS out_degree
FROM keyword
**LEFT** JOIN connection AS r1 ON **r1.kw2id** = keyword.kw_id
**LEFT** JOIN (
    SELECT kw2id AS id
    FROM connection AS conn
    WHERE conn.kw1id = [ID_CLICKED]
) AS child ON child.id = r1.kw1id
GROUP BY r1.kw1id
ORDER BY out_degree DESC

yeah I know, two answers to one question... but they're different answers :-)

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top