2017-03-16 38 views
2

使用SQL Server 2012.我有一個表中的成千上萬個組,我需要能夠選擇之外的所有頂級成員或一切根據每個羣組成員具有的數量,每個羣組的前兩名成員。這些組沒有明確地被調出,但是我可以使用窗口函數分配組編號。爲了說明我的問題,這裏的一些樣本數據:如何根據條件選擇每個組的x或y成員

Group Attribute ProductClass Product Quantity 
1  abc   xaxa   xx1000  16 
1  abc   xaxa   xx1019  15 
1  def   xaxa   xx1938  13 
1  abc   xaxa   xx1021  10 
2  def   xaxa   xx1031  18 
2  def   xaxa   xx3013  17 
2  abc   xaxa   xx4810  14 
3  abc   xaxb   xx0110  18 
3  def   xaxb   xx3810  15 
3  def   xaxb   xx2010  11 
3  def   xaxb   xx1002  8 
3  def   xaxb   xx1040  2 
3  abc   xaxb   xx0023  2 
4  def   xaxb   xx4918  14 
4  abc   xaxb   xx1414  11 
4  abc   xaxb   xx4182  11 
4  def   xaxb   xx1004  2 

下面是所需的輸出:

Group Attribute ProductClass Product Quantity 
1  def   xaxa   xx1938  13 
1  abc   xaxa   xx1021  10 
2  def   xaxa   xx3013  17 
2  abc   xaxa   xx4810  14 
3  def   xaxb   xx2010  11 
3  def   xaxb   xx1002  8 
3  def   xaxb   xx1040  2 
3  abc   xaxb   xx0023  2 
4  abc   xaxb   xx1414  11 
4  abc   xaxb   xx4182  11 
4  def   xaxb   xx1004  2 

有在「屬性」欄只有兩個屬性。請注意,對於「abc」,我希望按數量排列前兩個產品,而對於「def」,我只是希望按數量排列最前面的產品。

我已經創建了代碼,可以選擇以外的所有內容,以及可以分配組名稱的代碼。我只是不能擺脫這一部分:

SELECT 
     p.Group, 
     p.Attribute, 
     p.ProductClass, 
     p.Product, 
     p.Quantity 
FROM (SELECT *, 
       ROW_NUMBER() OVER(PARTITION BY ProductClass, Product ORDER BY Quantity DESC) AS RowNum, 
       DENSE_RANK() OVER(ORDER BY ProductClass, Product) AS Group 
     FROM table 
     WHERE brand = 'brand') AS p 
WHERE RowNum > 1; 

注意ProductClass和產品共同創造獨一無二的分組。

非常感謝!

+0

您的代碼實際上得到*所有,但*頂行各組中,但它是足夠接近。 –

+0

@GordonLinoff,感謝指出了這一點。這實際上是我想要的行爲。我編輯了這篇文章以反映這一點。 – mowshowitz

回答

0

Rank()而不是row_number()幾乎讓你那裏。問題是這些行並列第二名,而不是第三名。

SELECT p.Group, p.Attribute, p.ProductClass, p.Product, p.Quantity 
FROM (SELECT t.*, 
      RANK() OVER (PARTITION BY ProductClass, Product ORDER BY Quantity DESC) AS RowNum, 
      COUNT(*) OVER (PARTITION BY ProducctClass, Product, Count) as cnt, 
      DENSE_RANK() OVER (ORDER BY ProductClass, Product) AS Group 
     FROM table t 
     WHERE brand = 'brand' 
    ) AS p 
WHERE RowNum = 1 OR (RowNum = 2 AND cnt = 1); 

這會得到每組的最高值。另外,如果它沒有重複,並且它不匹配最高值,它將得到第二個值。這似乎是你想要的邏輯。

+0

我回復了你上面的評論。如果我要扭轉我原來的職位的行爲和選擇的一切,但頂部的結果或一切,而前兩個結果,又該'WHERE'條款樣子呢? 'WHN RowNum = 2 OR(RowNum> 2 AND cnt = 1)'? – mowshowitz

+0

@mowshowitz。 。 。我認爲它會是'(RowNum> 1或cnt> 1)'。 –