选择记录,如果有孩子,请选择最新的孩子

时间:2014-09-14 19:39:26

标签: sql

我有一张桌子:

element_id, element_parent_id

记录是:

1, null
2, 1
3, 1
4, null

因此,可视化可能如下所示:

1
  2
  3
4

问题是,如何选择:

form_id
3
4

...换句话说:如果没有孩子,如何选择父母,如果存在孩子,则选择最新的孩子。到目前为止,我设法选择:

1 and 4
2 and 3
1, 2, 3 and 4

1 个答案:

答案 0 :(得分:2)

为了更有用,我将解释我的推理到达最终查询(在底部)。

您正在从相同的表中选择两个不同的实体,因此您需要自己的JOIN表;这会给你父母和孩子。

但是孩子可能不在那里,所以它必须是LEFT JOIN

 SELECT p.id, c.id AS cid
 FROM yourtable AS p 
 LEFT JOIN yourtable AS c ON (c.parent_id = p.id);

+------+------+
| id   | cid  |
+------+------+
|    1 |    3 | # This one...
|    1 |    2 | # ...and this one must be grouped, and 3 taken.
|    3 | NULL | <-- this must be ignored because it's a child
|    4 | NULL |
|    2 | NULL | <-- this must be ignored because it's a child
+------+------+

现在要进一步完善,我们发现我们需要忽视父母&#34;中的孩子。角色和为此目的我们添加WHERE p.parent_id IS NULL。 &#34;真&#34;孩子有父母,然后会被跳过。

  

注意:如果我们有多层次的层次结构,那么我们需要做一些更复杂的事情。如果我们只想要   底层,即&#34; true&#34;孩子(忽略那些有父母的孩子   我们自己就是父母),例如我们可以运行第二个 LEFT JOIN   获得* grand *父母,并强加祖父母的身份不是   空值。这仅适用于三级和更大的孙子。要么   我们可以让孩子的孩子并强加他们的孩子   NULL id,即它们不存在;这仅适用于 bottom 或   最后一级的孩子。其他要求可能需要另一套   边界。

然后你想要&#34; top&#34;与父ID相关的子项,这需要GROUP BY,当孩子在那里时会产生所需的结果,或者在没有孩子时产生NULL。

 SELECT p.id, MAX(c.id) AS cid
     FROM yourtable AS p 
     LEFT JOIN yourtable AS c ON (c.parent_id = p.id)
     WHERE p.parent_id IS NULL
     GROUP BY p.id;

+------+------+
| id   | cid  |
+------+------+
|    1 |    3 |
|    4 | NULL |
+------+------+

的情况下,我们看到信息位于 -side列(id)。

要选择哪个,我会使用SUBSELECT

SELECT CASE WHEN cid IS NULL THEN id ELSE cid END AS wanted
FROM ( 

    SELECT p.id, MAX(c.id) AS cid 
    FROM yourtable AS p
    LEFT JOIN yourtable AS c ON (c.parent_id = p.id)
    WHERE p.parent_id IS NULL
    GROUP BY p.id 
) AS x;