2011-05-18 75 views
0

抓取下令行下面是从表中的某些条目:SQL查询:从表中

 
id  r_id  a_id  p_id

1 9 9 0 2 9 105 108 3 9 102 9 4 9 106 105 5 9 108 102

是否可以使用SQL查询来获取以下输出

 
1  9   9   0 
3  9   102   9 
5  9   108   102 
2  9   105   108 
4  9   106   105 

的想法是以这样的方式对行进行排序,使得具有p_id = x的行应该在a_id = x的行的下方。

我希望问题有道理。

问候,
Mayank

编辑:
我期待这对PostgreSQL

  • 根项目具有的p_id = 0
  • 没有缺失环节

回答

1

使用递归查询(PostgreSQL版本8.4或更高版本):

/* test data: 
CREATE TABLE foo (id, r_id, a_id, p_id) AS 
    SELECT 1,9,9,0 
    UNION ALL SELECT 2,9,105,108 
    UNION ALL SELECT 3,9,102,9 
    UNION ALL SELECT 4,9,106,105 
    UNION ALL SELECT 5,9,108,102   
; 
*/ 

-- the query you need: 
WITH RECURSIVE sub(s_id, s_r_id, s_a_id, s_p_id, row) AS (
    SELECT id, r_id, a_id, p_id, 1 AS row FROM foo WHERE p_id = 0 
UNION ALL 
    SELECT id, r_id, a_id, p_id, (row + 1) FROM foo JOIN sub ON s_a_id = p_id 
) 
SELECT * FROM sub ORDER BY row; 
+0

非常感谢。但是,只需要关于性能的建议。获取所有值然后在内存中对其进行排序会有多好/更糟糕? – Mayank 2011-05-18 07:49:27

+0

使用EXPLAIN ANALYZE查看查询的执行方式以及使用的内存量。根据您的情况,您可能需要对work_mem的设置进行一些更改。 – 2011-05-18 07:51:56

1

以下从适用的SQL Server 2005解决方案进行了改编。

我已经取得了一些假设

  • 根项目有p_id = 0
  • 没有缺失的环节

SQL语句

;WITH RECURSIVE q AS (
    SELECT * 
      , 1 AS Level 
    FROM ATable 
    WHERE p_id = 0 
    UNION ALL 
    SELECT t.* 
      , Level = Level + 1 
    FROM q 
      INNER JOIN ATable t ON t.p_id = q.a_id   
) 
SELECT * 
FROM q 
ORDER BY 
     Level 
+0

OP编辑了这个问题,他正在寻找一个与postgreSQL数据库兼容的答案。编辑前,我不会低调回答,但请考虑编辑您的答案。 – 2011-05-18 07:52:32

+1

@Johann - 我从来没有看过postgreSQL,但看着接受的答案和我的,你几乎没有注意到任何差异(递归似乎是唯一的)。 OP应该能够自己解决这个问题。 – 2011-05-18 08:01:13

+0

这两个答案都可以接受。当我意识到如何使用postgresql完成时,我得到了另一个答案。现在,我只能接受一个答案:)。 – Mayank 2011-05-18 08:38:41