帮我处理我的选择查询

时间:2011-03-02 06:58:12

标签: sql sql-server-2005

我在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返回活动学生。 但我也希望返回上一个和下一个活跃的学生的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 个答案:

答案 0 :(得分: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 :(得分: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

当没有匹配时,ISNULL将返回0 - NULL可以正常工作但是当没有Next时你的问题为0。

答案 2 :(得分:1)

您可能需要查看公用表表达式,这是仅用于SQL Server的递归查询功能,您可以找到链接here

但这听起来像是家庭作业,而且很可能不是正确的论坛。

此致

答案 3 :(得分: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

效率方面,我不知道此查询的执行情况

答案 4 :(得分: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     
;