2015-08-27 61 views
2

請參閱小提琴:http://sqlfiddle.com/#!6/e6768/2TSQL - 很難分組

我有數據,如下圖所示:

DRIVER DROP 
1  1 
1  2 
1  ReturnToBase 
1  4 
1  5 
1  ReturnToBase 
1  6 
1  7  
2  1 
2  2 
2  ReturnToBase 
2  4 

我想組我的數據,所以對於每個驅動器,每個組返回到基地有一個分組號碼。

我的輸出應該是這樣的:

DRIVER  DROP   GROUP 
1   1    1 
1   2    1 
1   ReturnToBase 1 
1   4    2 
1   5    2 
1   ReturnToBase 2 
1   6    3 
1   7    3 
1   ReturnToBase 3    
2   1    1   
2   2    1 
2   ReturnToBase 1 
2   4    2 

我試圖得到這個結果與窗口功能的組合,但我一直英里到目前爲止

下面是我有什麼,所以遠遠的說,它不應該是功能性的,我試圖弄清楚它是如何完成的,如果它甚至是可能的。

SELECT 
    ROW_NUMBER() OVER (Partition BY Driver order by Driver Desc) rownum, 
    Count(1) OVER (Partition By Driver Order By Driver Desc) counter, 
    Count 
    DropNo, 
    Driver, 
    CASE DropNo 
     WHEN 'ReturnToBase' THEN 1 ELSE 0 END AS EnumerateRound 
FROM 
    Rounds 
+0

您可以添加您嘗試過的sql嗎?看起來Row_Number應該適合這裏 – Mark

+0

您正在尋找某種遞歸LEAD LAG公用表表達式來完成此操作。 – saarrrr

+0

還有一個順序標識符,對不起,我應該在示例中包含該標識符。 –

回答

5

您可以使用下面的查詢:

SELECT id, DRIVER, DROPno, 
     1 + SUM(flag) OVER (PARTITION BY DRIVER ORDER BY id) - 
     CASE 
      WHEN DROPno = 'ReturnToBase' THEN 1 
      ELSE 0 
     END AS grp  
FROM (
    SELECT id, DRIVER, DROPno, 
     CASE 
      WHEN DROPno = 'ReturnToBase' THEN 1 
      ELSE 0 
     END AS flag 
    FROM rounds) AS t 

Demo here

此查詢OVER子句中使用的SUM窗口版本與ORDER BY來計算運行總和。此版本的SUM可從SQL Server 2012起向AFAIK提供。

爲了得到正確的GROUP值,我們需要用這個運行總值來擺弄一下。

編輯:(歸功於@Conrad Frix)

使用CROSS APPLY代替直列視圖可以顯着簡化的東西:

SELECT id, DRIVER, DROPno, 
     1 + SUM(x.flag) OVER (PARTITION BY DRIVER ORDER BY id) - x.flag 
FROM rounds 
CROSS APPLY (SELECT CASE WHEN DROPno = 'ReturnToBase' THEN 1 ELSE 0 END) AS x(flag) 

Demo here

+0

完美,我走了。謝謝 –

+0

如果您想要別名單個計算,您可能需要考慮使用交叉應用而不是內聯視圖.. [例如](http://data.stackexchange.com/stackoverflow/query/356003) –

+0

@ConradFrix你是對的,非常感謝! –

2

添加順序ID列以您的示例用於遞歸CTE:

with cte as (
select ID,DRIVER,DROPno,1 as GRP 
FROM rounds 
where ID = 1 
union all 
select a.ID 
,a.DRIVER 
,a.DROPno 
,case when b.DROPno = 'ReturnToBase' 
     or b.DRIVER <> a.DRIVER then b.GRP + 1 
     else b.GRP end 
from rounds a 
    inner join cte b 
    on a.ID = b.ID + 1 
) 

select * from cte 

SQL Fiddle