根据联接优先级列的最低值选择不同的标识行

时间:2009-09-19 18:12:53

标签: sql mysql greatest-n-per-group

简化表结构,所有INT列以及标识列之外没有PK:

节点(n)表:id

属性(a)表:idnode_idtype_id

类型(t)表:idpriority

我正在尝试选择一组属性,每个属性对应的节点都具有最低的type.priority。虽然每node_id有多个属性,但我只想选择具有最低优先级值的属性:

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

这是我正在处理的基本查询,此时我也陷入困境:

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

我的第一个想法是使用聚合MIN,但是我遇到了将node_id的最低优先级与正确属性匹配的问题。

2 个答案:

答案 0 :(得分:2)

使用tie-breaker查询(未测试):

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
                    )

答案 1 :(得分:2)

这个问题是“每组最大n个”问题的变体,但是你要找的是最少的而不是最大的,而你的标准是在查找表(Type)中原则表(Attributes)。

因此,您希望来自a1的行(Attributes)使得具有相同node_id的其他行与较低优先级相关联。

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;

请注意,这可能会导致联系。如果两个属性引用具有相同优先级的类型,则您尚未描述如何解析关系。换句话说,在以下示例中,应选择哪些属性?

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

PS:我希望你不介意我在你的问题中添加了“每组最大的”标签。点击该标签,查看我已经标记过类似的其他问题。