2015-05-09 163 views
2

我不知道如何以一般的方式解釋了這一點,所以讓我來舉個例子段發現某些行。的SQL Server 2008 R2:整蠱查詢 - 行

SELECT ParentId, Id, Number 
FROM SomeTable 
ORDER BY ParentId, Id 

ParentId Id  Number 
2997 1145445 400 
2997 1145449 400 
2997 1145577 400 
2997 1146518 405 
2999 1145470 400 
2999 1145502 400 
2999 1145504 400 
3016 1145633 400 
3016 1145636 400 
3016 1145677 400 
3016 1145686 405 
3037 1145885 400 
3037 1145906 405 
3037 1145922 400 
3037 1145925 400 
3162 1147324 400 
3162 1147327 400 
3162 1147329 400 
3162 1147332 400 
3162 1147334 405 
3162 1147339 400 
3162 1147341 405 
3162 1147345 406 
3162 1147347 410 

(這只是實際數據的一個子集,但足以說明問題)。

問題:與Number = 400但有以下的列選擇準確的所有行

查詢(如優雅和儘可能高效,優選沒有子查詢,光標等)加入:

Id_405 :的行的IdNumber = 405並且這400和下一個400之間的相同ParentId,如上述有序按ID。這是保證最多有一個405 Id_405爲空,如果不存在這樣的405

Id_406:該行的IdNumber = 406,這400和下400之間的相同ParentId,如上面下令ID。這是保證最多有一個406 Id_406爲空,如果不存在這樣的406

Id_410:該行與Number = 410,這400和下400之間的相同ParentId的ID,如上面下令ID。這是保證最多有一個406 Id_410爲空,如果不存在這樣的410

通過上述例子的數據,查詢將返回:

ParentId Id Number Id_405 Id_406 Id_410 
2997 1145445 400  null null null 
2997 1145449 400  null null null 
2997 1145577 400  1146518 null null 
2999 1145470 400  null null null 
2999 1145502 400  null null null 
2999 1145504 400  null null null 
3016 1145633 400  null null null 
3016 1145636 400  null null null 
3016 1145677 400  1145686 null null 
3037 1145885 400  1145906 null null 
3037 1145922 400  null null null 
3037 1145925 400  null null null 
3162 1147324 400  null null null 
3162 1147327 400  null null null 
3162 1147329 400  null null null 
3162 1147332 400  1147334 null null 
3162 1147339 400  1147341 1147345 1147347 

請幫幫忙!

+0

Id_405,Id_406和Id_410的概念不清楚。解釋清楚,以便人們可以回答這個問題。 –

+0

您使用的是哪個版本的sql server? –

+0

我不確定關於Id_405,Id_406和Id_410的什麼不清楚?他們在上面分別進行了解釋並給出了一個例子。我不知道還有什麼補充不知道你的想法不清楚。 – pinkfloydhomer

回答

1

可以單獨編號的行,然後加入像那些排名:

SELECT 
    t.parentid, t.id, t.number, t1.id, t2.id, t3.id 
FROM 
    (SELECT *, ROW_NUMBER() OVER (PARTITION BY parentid ORDER BY id DESC) rn 
    FROM t 
    WHERE number = 400) t 
    LEFT JOIN 
    (SELECT *, ROW_NUMBER() OVER (PARTITION BY parentid ORDER BY id DESC) rn 
    FROM t 
    WHERE number = 405) t1 ON t.parentid = t1.parentid AND t.rn = t1.rn 
    LEFT JOIN 
    (SELECT *, ROW_NUMBER() OVER (PARTITION BY parentid ORDER BY id DESC) rn 
    FROM t 
    WHERE number = 406) t2 ON t.parentid = t2.parentid AND t.rn = t2.rn 
    LEFT JOIN 
    (SELECT *, ROW_NUMBER() OVER (PARTITION BY parentid ORDER BY id DESC) rn 
    FROM t 
    WHERE number = 410) t3 ON t.parentid = t3.parentid AND t.rn = t3.rn 
ORDER BY t.parentid, t.rn DESC 

這裏是fiddle demo

+0

可以爲't1.id,t2.id,t3.id';添加別名。 –

0

Fiddle Demo

,如果你認爲我不知道這個優雅高效,但結果是一樣的:

select * 
from sometable d400 
outer apply (
    select top 1 id id_400n 
    from sometable 
    where sometable.number=400 
    and sometable.parentid=d400.parentid 
    and sometable.id>d400.id 
    order by id 
) d400n 
outer apply (
    select top 1 id id_405 
    from sometable 
    where sometable.number=405 
    and sometable.parentid=d400.parentid 
    and sometable.id between d400.id and coalesce(d400n.id_400n,9999999) 
    order by id 
) d405 
outer apply (
    select top 1 id id_406 
    from sometable 
    where sometable.number=406 
    and sometable.parentid=d400.parentid 
    and sometable.id between d400.id and coalesce(d400n.id_400n,9999999) 
    order by id 
) d406 
outer apply (
    select top 1 id id_410 
    from sometable 
    where sometable.number=410 
    and sometable.parentid=d400.parentid 
    and sometable.id between d400.id and coalesce(d400n.id_400n,9999999) 
    order by id 
) d410 
where d400.number=400 
order by d400.id 
+0

查詢結果與OP的結果不同,請檢查;)。 –

+0

@ shA.t它可能會錯過訂單,但這是唯一的區別。我真的懷疑,「我不知道你認爲這種優雅和高效」比我的英語更好。 –

+0

首先,使用'd400.ParentId,d400.id'命令而不是那個,然後你的結果中有'id400n'列,我認爲OP需要刪除它;並且只要你想編輯就行;)。 –

2

作者:Dan該解決方案實際上並不產生正確的結果 - 所以在相似的樣式我已經發布,似乎產生正確的結果之一。

Fiddle demo

WITH r AS (
    SELECT t1.parentid 
     , t1.id 
     , t1.number 
     , ISNULL(t2.id,2147483647) as id2 
     , row = ROW_NUMBER() OVER (PARTITION BY t1.parentid, t1.id ORDER BY t1.id, t2.id) 
    FROM   t t1 
    LEFT JOIN t t2 
     ON  t1.id < t2.id 
     AND  t1.parentid = t2.parentid 
     AND  t2.number = 400 
    WHERE   t1.number = 400 
) 
SELECT r.parentid, r.id, r.number, t_405.id as id_405, t_406.id as id_406, t_410.id as id_410 
FROM   r 
    LEFT JOIN t  t_405 
    ON  t_405.parentid = r.parentid 
    AND  t_405.id BETWEEN r.id AND r.id2 
    AND  t_405.number = 405 
    LEFT JOIN t  t_406 
    ON  t_406.parentid = r.parentid 
    AND  t_406.id BETWEEN r.id AND r.id2 
    AND  t_406.number = 406 
    LEFT JOIN t  t_410 
    ON  t_410.parentid = r.parentid 
    AND  t_410.id BETWEEN r.id AND r.id2 
    AND  t_410.number = 410 
WHERE r.row = 1 
+0

我檢查了Dan的答案的結果,那麼它的問題是什麼? )。 –

+0

我看到您的查詢返回與我的結果沒有區別。兩者都符合願望的結果。 –

+0

@Dan第1145885行應該包含405的值,但它會轉到1145925(在同一父母標識下) 抱歉無法對您的帖子發表評論。 – user4882995