2011-03-02 79 views
1

我在SQL Server 2005中的表:帮我选择查询

id student active 
1 Bob  1 
3 Rob  0 
5 Steve 1 
7 John 1 
8 Mark 0 
10 Dave 0 
16 Nick 1 

我的选择查询由给定id返回一个活跃的学生。 但我也想要返回活跃的prev和next学生的ID。如果没有prev,它将为0或null。下一个相同。

示例:对于ID = 5,我的选择数据将返回

id student prev_id next_id 
5  steve  1   7 

示例:对于ID = 7,我的选择数据将返回

id student prev_id next_id 
7  John  5   16 

示例:对于ID = 16,我的选择将返回

id student prev_id next_id 
16 Nick  7   0 

如何编写此选择查询?

我有查询,但我无法正确获得prev id。它总是返回第一个活动的ID。

感谢

编辑: 下面是该查询我现在所拥有的。

select id, student, 
(select top 1 id from test where id<7 and active=1) as prev, 
(select top 1 id from test where id>7 and active=1) as next 
from test where id=7--I used 7 just as an example. it will be a parameter 
+5

您的查询是什么? – Nishant 2011-03-02 07:00:28

+0

我可以想到一些非常讨厌的相关子查询,它们会得到你想要的,但是这个要求的原因是什么?也许有不同的方式来满足这个要求。 – 2011-03-02 07:06:16

+0

select test,student, (select test test from test where id <7 and active = 1)as prev, (select top 1 id from test where id> 7 and active = 1)as next from test where id = 7 - 我将使用7 – kheya 2011-03-02 07:06:18

回答

5

尝试这样的事情

SELECT ID, 
     Student, 
     (SELECT TOP 1 
        ID 
      FROM  dbo.table AS pT 
      WHERE  pT.ID < T.ID And Active = 1 
      ORDER BY ID DESC 
     ) AS PrevID, 
     (SELECT TOP 1 
        ID 
      FROM  dbo.table AS pT 
      WHERE  pT.ID > T.ID And Active = 1 
      ORDER BY ID 
     ) AS NextID 
FROM dbo.table AS T 
1

你可能想看看公共表表达式,仅适用于SQL Server进行递归查询功能,你可以找到一个链接here

但这个声音像作业,并探讨不是正确的论坛问它。

关注

+0

这不是一项家庭作业。我看到你被标记了。但这是一个真正的问题。我只是以不同的方式表达,使其更容易理解。 – kheya 2011-03-02 07:10:45

1

您可以使用嵌套查询。我显然不能测试这个,但你应该明白。

SELECT id, student , 
(SELECT C1.id FROM students S1 WHERE S1.active = 1 AND S1.id < S.id LIMIT 1) AS beforeActive, 
(SELECT C2.id FROM categories S2 WHERE S2.active = 1 AND S2.id > S.id LIMIT 1) AS afterActive 
FROM students S 

效率明智的,我不知道该查询性能如何

2

工作样本

DECLARE @T TABLE (id int, student varchar(10), active bit) 
insert @t select 
1 ,'Bob', 1 union all select 
3 ,'Rob', 0 union all select 
5 ,'Steve', 1 union all select 
7 ,'John', 1 union all select 
8 ,'Mark', 0 union all select 
10 ,'Dave', 0 union all select 
16 ,'Nick', 1 

---- your query starts below this line 

declare @id int set @id = 5 

select id, student, 
    isnull((select top(1) Prev.id from @T Prev 
    where Prev.id < T.id and Prev.active=1 
    order by Prev.id desc),0) Prev, 
    isnull((select top(1) Next.id from @T Next 
    where Next.id > T.id and Next.active=1 
    order by Next.id),0) Next 
from @T T 
where id = @id 

的ISNULLs是返回0;如果没有匹配 - NULL会工作没问题,但是当没有Next时,你的问题有0。

0

这会给你一点控制权,尤其是因为你正在分页。

WITH NumberedSet AS (
    SELECT s.id, 
      s.student, 
      row_number() OVER (ORDER BY s.id) AS rownum 
    FROM dbo.students AS s 
    WHERE s.active = 1 
) 
SELECT cur.id, 
     cur.student, 
     isnull(prv.id,0) AS prev_id, 
     isnull(nxt.id,0) AS next_id 
FROM NumberedSet AS cur 
     LEFT JOIN NumberedSet AS prv ON cur.rownum - 1 = prv.rownum 
     LEFT JOIN NumberedSet AS nxt ON cur.rownum + 1 = nxt.rownum  
;