2011-11-28 49 views
0

我有一个(传统)表中有列:SQL自联接的多个属性

bug_num build_id closed_to 
1   3   NULL 
2   4   NULL 
3   NULL   1 
4   3   NULL 
5   NULL   2 

我想编写一个查询它从一个特定的构建选择所有的错误,所有的bug被关闭到该构建中的错误。所以,如果我想为build 3做它,它会包含#1和4(因为它们在build 3中),还有3,因为它被关闭到build 3(1)中的一个bug。

我以为我亲近:

SELECT stat.bug_num, 
     stat.build_id 
FROM bug_status stat 
     JOIN bug_status stat2 
     ON stat2.closed_to = stat.bug_num 
WHERE stat.build_id = 3; 

...但它似乎并没有被给我想要的结果。谢谢你的帮助!

+0

要澄清,“关闭”不是构建ID,它是一个错误号。 – pennstatephil

回答

2
SELECT stat.bug_num, 
     stat.build_id 
    FROM bug_status stat 
WHERE stat.build_id = 3 
    OR stat.closed_to IN 
     (SELECT stat2.bug_num 
      FROM bug_status stat2 
      WHERE stat2.build_id = 3 
     ) 
; 

(也有可能与JOIN要做到这一点,或与JOIN和UNION,但我相信上面是最直观的方式。)


编辑补充:这里是一个MySQL转录物证实以上:

mysql> create table bug_status 
    -> (bug_num numeric, build_id numeric, closed_to numeric); 
Query OK, 0 rows affected (0.01 sec) 

mysql> insert into bug_status values (1, 3, null); 
Query OK, 1 row affected (0.00 sec) 

mysql> insert into bug_status values (2, 4, null); 
Query OK, 1 row affected (0.01 sec) 

mysql> insert into bug_status values (3, null, 1); 
Query OK, 1 row affected (0.00 sec) 

mysql> insert into bug_status values (4, 3, null); 
Query OK, 1 row affected (0.00 sec) 

mysql> insert into bug_status values (5, null, 2); 
Query OK, 1 row affected (0.00 sec) 

mysql> SELECT stat.bug_num, 
    ->  stat.build_id 
    -> FROM bug_status stat 
    -> WHERE stat.build_id = 3 
    ->  OR stat.closed_to IN 
    ->   (SELECT stat2.bug_num 
    ->    FROM bug_status stat2 
    ->   WHERE stat2.build_id = 3 
    ->  ) 
    -> ; 
+---------+----------+ 
| bug_num | build_id | 
+---------+----------+ 
|  1 |  3 | 
|  3 |  NULL | 
|  4 |  3 | 
+---------+----------+ 
3 rows in set (0.00 sec) 

编辑补充,因为IN (...)的做法似乎并没有在OP的版本的MySQL的工作:下面是给出了同样结果的替代查询:

SELECT stat.bug_num, 
     stat.build_id 
    FROM bug_status stat 
    LEFT 
OUTER 
    JOIN bug_status stat2 
    ON stat.closed_to = stat2.bug_num 
WHERE stat.build_id = 3 
    OR stat2.build_id = 3 
; 
+0

不幸的是,构建ID是当一个错误关闭到另一个错误时被清除,因为它不知道什么时候会实际执行另一个错误,所以我需要将closed_to直接映射到bug_num ... – pennstatephil

+0

重新读取,它看起来像您的解决方案可能工作,但对于一些因为sql似乎不喜欢嵌套查询。 – pennstatephil

+0

@pennstatephil:很奇怪。我刚刚在MySQL版本5.1.53上测试了我的查询,并返回了正确的行。你有可能错误地复制了一些东西吗? – ruakh

2

您还没有包括stat2.build_id您的WHERE子句(我认为从错误的表中取得您的ON列):

SELECT stat.bug_num, stat.build_id 
FROM bug_status stat 
LEFT JOIN bug_status stat2 
ON stat.closed_to = stat2.bug_num 
WHERE stat.build_id = 3 OR stat2.build_id = 3 
+0

很奇怪......如果我完全删除了where子句,它会给出一堆带有bug ID 0和build ID为null的行。似乎连接没有妥善把表连接在一起? – pennstatephil

+0

这是不对的。它有几个问题;例如,'stat2.build_id = 3'永远不会是真的,因为每当'bug_status.closed_to IS NOT NULL'时(至少在问题中的示例数据中)都是'bug_status.build_id IS NULL'。 – ruakh

+1

试试'ON stat.closed_to = stat2。bug_num' – knittl

0

为什么不:

DECLARE @build_id int = <the build id> 

SELECT stat.bug_num, stat.build_id, stat.closed_to 
FROM  bug_status stat 
WHERE stat.build_id = @build_id 
    OR stat.closed_to = @build_id 

+0

SQL上的+1,但语法看起来像TSQL而不是MySQL。你可能最好删除声明并在你的答案中输入文字值,并让OP找出如何处理参数 –

+3

'closed_to'映射到'bug_num'而不是'build_id' – knittl

0

此查询...

SELECT * 
FROM bug_status t1 
WHERE 
    build_id = 3 
    OR EXISTS (
     SELECT * 
     FROM bug_status t2 
     WHERE 
      t2.build_id = 3 
      AND t1.closed_to = t2.bug_num 
    ) 

...产生以下结果:

bug_num build_id closed_to 
1   3   NULL 
3   NULL  1 
4   3   NULL 

用简单的英语:选择行这样的:

  • build_id = 3
  • 或者存在与build_id = 3相关的行。