2015-10-09 31 views
-4

如何在查詢中實現增量分組?增量組BY BY

enter image description here

我需要GROUP BY所有非零值到不同的命名組。

請幫我寫一個基於列日期和訂閱者的查詢。

+4

請解釋你的輸出。 – DarkKnight

+3

爲'group1','group2'添加表格定義,樣本數據和您的查詢 – Backs

+0

...瞭解序列,對於'無組',它位於行的頂部。 – Ajay2707

回答

1

如果您有SQL Server 2012中或更高版本,可以使用一些小技巧與Windows函數來獲取這樣的分組沒有光標,像這樣的東西:

select 
    Date, Subscribers, 
    case when Subscribers = 0 then 'No group' 
    else 'Group' + convert(varchar, GRP) end as GRP 
from (
    select 
    Date, Subscribers, 
    sum (GRP) over (order by Date asc) as GRP 
    from (
    select 
     *, 
     case when Subscribers > 0 and 
     isnull(lag(Subscribers) over (order by Date asc),0) = 0 then 1 else 0 end as GRP 
    from SubscribersCountByDay S 
) X 
) Y 

實例SQL Fiddle

1

總的來說,我提倡不贊同遊標,但在這種情況下,它生病沒有受到傷害,因爲它不適合迭代,總結並且一次完成條件。 另請注意我用FAST_FORWARD暗示它不會降低性能。

我猜你確實想要@HABO評論。

查看下面的工作示例,它只是總結,直到找到零,重置並重新開始。請注意0​​處理第一行爲零的情況。

create table dbo.SubscribersCountByDay 
(
    [Date] date not null 
    ,Subscribers int not null 
) 

GO 

insert into dbo.SubscribersCountByDay 
([Date], Subscribers) 
values 
('2015-10-01', 1) 
,('2015-10-02', 2) 
,('2015-10-03', 0) 
,('2015-10-04', 4) 
,('2015-10-05', 5) 
,('2015-10-06', 0) 
,('2015-10-07', 7) 

GO 

declare 
@Date date 
,@Subscribers int 
,@Sum int = 0 
,@GroupId int = 1 

declare @Result as Table 
(
    GroupName varchar(10) not null 
    ,[Sum] int not null 
) 

declare ScanIt cursor fast_forward 
for 
(
    select [Date], Subscribers 
    from dbo.SubscribersCountByDay 
    union 
    select '2030-12-31', 0 
) order by [Date] 
open ScanIt 

fetch next from ScanIt into @Date, @Subscribers 

while @@FETCH_STATUS = 0 
begin 

    if (@Subscribers = 0 and @Sum > 0) 
    begin 
     insert into @Result (GroupName, [Sum]) values ('Group ' + cast(@GroupId as varchar(6)), @Sum) 
     set @GroupId = @GroupId + 1 
     set @Sum = 0 
    end 
    else begin 
     set @Sum = @Sum + @Subscribers 
    end 

    fetch next from ScanIt into @Date, @Subscribers 
end 

close ScanIt 
deallocate ScanIt 


select * from @Result 
GO 

對於OP:請在下一次寫表,剛剛發佈的圖像是懶惰

+0

你可能想看看基於集合的答案。遊標並不是真的需要。 – HABO

+0

@HABO該解決方案雖然是我的第一個,但爲了表現我重新考慮它需要在原始數據中迭代至少兩次,其中一個用於「構建」組,另一個用於聚合。這裏的遊標將所有內容都包裹在一起。還有一大堆你生病需要更多的記憶。記住遊標是不推薦的,因爲它會花費(循環和內存),但在這種情況下它不好表現更好恕我直言 – jean

1

在現代足以支持熱膨脹係數可以用一個個版本的SQL Server E採用無遊標查詢:

-- Sample data. 
declare @SampleData as Table (Id Int Identity, Subscribers Int); 
insert into @SampleData (Subscribers) values 
    -- (0), -- Test edge case when we have a zero first row. 
    (200), (100), (200), 
    (0), (0), (0), 
    (50), (50), (12), 
    (0), (0), 
    (43), (34), (34); 
select * from @SampleData; 

-- Run the query. 
with ZerosAndRows as (
    -- Add IsZero to indicate zero/non-zero and a row number to each row. 
    select Id, Subscribers, 
    case when Subscribers = 0 then 0 else 1 end as IsZero, 
    Row_Number() over (order by Id) as RowNumber 
    from @SampleData), 
    Groups as (
    -- Add a group number to every row. 
    select Id, Subscribers, IsZero, RowNumber, 1 as GroupNumber 
    from ZerosAndRows 
    where RowNumber = 1 
    union all 
    select FAR.Id, FAR.Subscribers, FAR.IsZero, FAR.RowNumber, 
    -- Increment GroupNumber only when we move from a non-zero row to a zero row. 
    case when Groups.IsZero = 1 and FAR.IsZero = 0 then Groups.GroupNumber + 1 else Groups.GroupNumber end 
    from ZerosAndRows as FAR inner join Groups on Groups.RowNumber + 1 = FAR.RowNumber 
) 
-- Display the results. 
select Id, Subscribers, 
    case when IsZero = 0 then 'no group' else 'Group' + Cast(GroupNumber as VarChar(10)) end as Grouped 
    from Groups 
    order by Id; 

要查看中間結果只是select * from FlagsAndRowsselect * from Groups更換最終select