2012-01-16 48 views
1

我在MySQL中有一个简单的层次结构component,该表由assembly表描述。SQL - 在层次结构中唯一选择(可能缺少)子项

SELECT * FROM component; 

+----+--------+------+ 
¦ id ¦ name ¦ type ¦ 
+----+--------+------+ 
¦ 11 ¦ car1 ¦ A ¦ 
¦ 12 ¦ car2 ¦ A ¦ 
¦ 13 ¦ car3 ¦ A ¦ 
¦ 21 ¦ motor1 ¦ B ¦ 
¦ 22 ¦ motor2 ¦ B ¦ 
¦ 31 ¦ brake1 ¦ C ¦ 
+----+--------+------+ 

SELECT * FROM assembly; 

+----+-----------+----------+ 
¦ id ¦ parent_id ¦ child_id ¦ 
+----+-----------+----------+ 
¦ 1 ¦  11 ¦  21 ¦ 
¦ 2 ¦  12 ¦  22 ¦ 
¦ 3 ¦  11 ¦  31 ¦ 
¦ 4 ¦  13 ¦  31 ¦ 
+----+-----------+----------+ 

编辑:正如德姆正确猜测,原始帖子中缺少第三项(id = 3)。该表现在完成。

我想生成一个所有汽车的名单,其电机的名称,如果有的话。每辆车应该出现一次。

所需的输出:

+----------+------------+ 
¦ car_name ¦ motor_name ¦ 
+----------+------------+ 
¦  car1 ¦  motor1 ¦ 
¦  car2 ¦  motor2 ¦ 
¦  car3 ¦   ¦ 
+----------+------------+ 

有一个简单的方法来获得呢?

一辆汽车至多有一个汽车的孩子。

外连接与电动机部件的视图产生两行car1和这不应该发生:

CREATE VIEW comp_motor 
AS 
SELECT * FROM component 
WHERE type='B'; 

SELECT parent.name, child.name 
FROM component parent 
LEFT JOIN assembly a ON parent.id = a.parent.id 
LEFT JOIN comp_motor child ON a.child_id = child.id 
WHERE 
parent.type = 'A'; 

这给出

+------+--------+ 
¦ name ¦ name ¦ 
+------+--------+ 
¦ car1 ¦ motor1 ¦ 
¦ car1 ¦ NULL ¦ 
¦ car2 ¦ motor2 ¦ 
¦ car3 ¦ NULL ¦ 
+------+--------+ 

第二行不应该存在。当然DISTINCT在这种情况下不会起作用。

我无法更改数据库结构。

任何投入将是最受欢迎的!

+0

你应该使用内部连接,如果你不想让第二排。 – Reddy 2012-01-16 11:45:34

回答

2

你能运行下面的SELECT语句并告诉我们你得到了什么吗?

SELECT * FROM component WHERE type = 'A' 

我想你在那里两次有Car1 ...

编辑

哦,否则你有两个记录分享帮助在装配表?这显示了什么?

SELECT * FROM assembly WHERE parent_id = 11 

如果是这样的源,试试这个...

SELECT 
    parent.name, 
    child.name 
FROM 
    component parent 
LEFT JOIN 
    (
    assembly a 
    INNER JOIN 
    comp_motor child 
     ON a.child_id = child.id 
) 
    ON parent.id = a.parent.id 
WHERE 
    parent.type = 'A'; 
+0

您在原帖中指出了确切的错误,非常感谢。我现在纠正它。 'assembly'表中缺少一个条目。你的解决方案给出了我正在寻找的东西。 – Adrien 2012-01-16 12:51:44

+0

@Dems +1看得见! – 2012-01-16 12:58:16

0

尝试:

select car.name car_name, coalesce(motor.name, 'No motor') motor_name 
from component car 
left join (select a.parent_id, c.name 
      from assembly a 
      inner join component c 
        on a.child_id = c.id and c.type = 'B') motor 
     on car.id = motor.parent_id 
where car.type = 'A' 
+0

你的解决方案工作得很好。非常感谢。 – Adrien 2012-01-16 12:56:37