2011-03-02 29 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  
;