2014-11-22 96 views
2

根據未取消日​​期選擇第一個活動以及是否取消所有活動以選擇第一個活動的最佳方法是什麼?Top 1 with where子句 - 如果沒有找到記錄,則忽略where子句

方案有樣本數據:

create table SomeOtherTable 
(
    Id bigint primary key 
) 

create table activities 
(
    Id bigint identity(1,1) primary key, 
    SomeForeignKey bigint, 
    Description varchar(100), 
    Date datetime, 
    Canceled bit 
) 


insert into SomeOtherTable values (1),(2),(3) 

insert into activities values (1, 'Activity 1', '20141201', 1), 
           (1, 'Activity 2', '20141203', 0), 
           (1, 'Activity 3', '20141205', 0), 
           (2, 'Activity 4', '20141207', 1), 
           (2, 'Activity 5', '20141209', 1), 
           (3, 'Activity 6', '20141209', 0) 

希望的輸出:

活動2 - 2014年12月3日 - 0

活動4 - 十二分之二千零一十四/ 07 - 1

活動6 - 2014/12/0 9 - 0

我目前使用此查詢,但我認爲必須有一個更好的解決辦法...

select case when a1.Id is null then a2.Description else a1.Description end as Description, 
     case when a1.Id is null then a2.Date else a1.Date end as Date, 
     case when a1.Id is null then a2.Canceled else a1.Canceled end as Canceled 
from SomeOtherTable t 
outer apply (select top 1 * 
      from activities a 
      where t.id=a.SomeForeignKey 
      and a.Canceled = 0 
      order by a.Date) a1 

cross apply (select top 1 * 
      from activities a 
      where t.id=a.SomeForeignKey    
      order by a.Date) a2 

SQL Fiddle link

回答

2

你想要的結果優先級,與Canceled = 0首先,然後是任何其他行。你可以用一個outer apply做到這一點:

select a.Description, a.Date, a.Canceled 
from SomeOtherTable t outer apply 
    (select top 1 * 
     from activities a 
     where t.id = a.SomeForeignKey 
     order by (case when a.canceled = 0 then 1 else 0 end) desc, a.Date 
    ) a; 

我通常會提出相似的邏輯在row_number()計算,但outer apply作品一樣好。

編輯:

爲了完整和比較,這裏是row_number()方法:

select a.Description, a.Date, a.Canceled 
from SomeOtherTable t left join 
    (select a.*, 
      row_number() over (partition by a.SomeForeignKey 
           order by (case when a.canceled = 0 then 1 else 0 end) desc, a.Date 
           ) as seqnum 
     from activities a 
    ) a 
    on t.id = a.SomeForeignKey and seqnum = 1; 

在一般情況下,我認爲apply方法是凌晨快一點 - 從本質上講,它停靠在第一匹配行並且不需要繼續處理給予t.id

+0

這實際上是有道理的......我太過於複雜。我也用'row_number'試過了,沒有成功。感謝你! – Hatsjoem 2014-11-22 22:37:21