Question

Simplified table structures, all INT columns and no PKs outside of the identity columns:

Nodes (n) table: id

Attributes (a) table: id, node_id, type_id

Type (t) table: id, priority

I'm trying to select a set of attributes, each of which has the lowest type.priority for its respective node. Though there are multiple attributes per node_id, I only want to select the one with the lowest priority value:

a1 n1 t1 p0 *
a2 n1 t2 p1 
a3 n2 t2 p1 *
a4 n2 t3 p2  

This is the basic query that I'm working from, at which point I'm also getting stuck:

   SELECT * 
     FROM a 
LEFT JOIN t ON a.type_id = t.id 
 GROUP BY node_id

My first thought was to use an aggregate, MIN, but I'm then having problems matching up the lowest priority for a node_id with the correct attribute.

Was it helpful?

Solution

This question is a variation of the "greatest-n-per-group" problem, but you're looking for the least instead of the greatest, and your criteria are in a lookup table (Type) instead of the principle table (Attributes).

So you want the rows (a1) from Attributes such that no other row with the same node_id is associated with a lower priority.

SELECT a1.*
FROM Attributes a1 INNER JOIN Type t1 ON (a1.type_id = t1.id)
LEFT OUTER JOIN (
  (Attributes a2 INNER JOIN Type t2 ON (a2.type_id = t2.id))
  ON (a1.node_id = a2.node_id AND t1.priority > t2.priority)
WHERE a2.node_id IS NULL;

Note that this can result in ties. You haven't described how you would resolve ties if two Attributes referenced Types with the same priority. In other words, in the following examples, which attributes should be selected?

a1 n1 t1 p0 
a2 n1 t1 p0 
a3 n2 t2 p1 
a4 n2 t3 p1 

PS: I hope you don't mind I added the "greatest-n-per-group" tag to your question. Click that tag to see other questions on SO that I have tagged similarly.

OTHER TIPS

Use tie-breaker query (not tested):

SELECT      n.*, a.*
FROM        Nodes n
LEFT JOIN   Attributes a
        ON  a.id = (SELECT      x.id --//TOP 1 x.id
                    FROM        Attributes x
                    INNER JOIN  Type t
                            ON  x.type_id = t.id
                    WHERE       x.node_id = n.id
                    ORDER BY    t.priority ASC,
                                --//just in case there are 2 attributes 
                                --//with the same priority, order also on x.id
                                x.id ASC
                    LIMIT 1
                    )
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top