2012-12-27 57 views
1

我有臨時表(@TempPackages),它看起來是這樣的:如何查找包含SQL Server中特定列的MIN/MAX值的所有(基於組)的行?

EntryId (PK) PackageId SubProductID SubProductSequence 
1    1111   17    3 
2    1111   28    4 
3    1111   33    1 
4    1111   67    5 
5    1111   122    2 
6    2222   18    4 
7    2222   29    5 
8    2222   33    9 
9    2222   103    7 
10    2222   99    11 
11    3333   256    5 
12    3333   333    6 
13    3333   789    3 
14    3333   1023   2 
15    3333   9845   1 

我需要一個查詢,這將給我的最小/最大SubProductSequence值的行,每一個獨特的PackageId。對於上面的表,查詢將返回此:

EntryId (PK) PackageId SubProductID SubProductSequence 
3    1111   33    1 
4    1111   67    5 
6    2222   18    4 
10    2222   99    11 
12    3333   333    6 
15    3333   9845   1 

EntryId列是我加入,同時試圖解決這個問題,因爲它給了我一個獨特的列加入到同一個表(以確保我的東西仍然只有在我的連接表中有15行)。

我嘗試這樣做 - 只是爲了讓MIN()

SELECT 
    * 
FROM 
    @TempPackages p1 
INNER JOIN 
    @TempPackages p2 ON p1.EntryId = p2.EntryId 
    AND p1.SubProductSequence = (
     SELECT 
      MIN(SubProductSequence) 
     FROM 
      @DeparturesToUpdate) 

這顯然是錯誤的,因爲INNER JOIN是多餘的和SELECT MIN()條款是錯誤的,因爲它選擇具有最小整體序列號的行,而不是每個包的最小序列號

任何有關最佳方式的建議嗎?

+0

@MitchWheat - 我看不到任何不一致。你能詳細說明嗎? – LeopardSkinPillBoxHat

+0

我的錯誤:min和max分別在輸出中。 –

回答

4

的一種方法是使用ROW_NUMBER()功能:

SELECT 
    EntryId 
    , PackageId 
    , SubProductID 
    , SubProductSequence 
FROM 
    (SELECT 
     EntryId 
     , PackageId 
     , SubProductID 
     , SubProductSequence 
     , ROW_NUMBER() OVER (PARTITION BY PackageId 
          ORDER BY SubProductSequence ASC) 
      AS rna 
     , ROW_NUMBER() OVER (PARTITION BY PackageId 
          ORDER BY SubProductSequence DESC) 
      AS rnd 
    FROM 
     @TempPackages 
) AS tmp 
WHERE 
     rna = 1 
    OR rnd = 1 ; 

ROW_NUMBER()是使用OVER子句的排序功能。它在這種情況下基本上做了什麼,它是否將同行PackageId(即PARTITION BY PackageId完成)分組,然後按SubProductSequence(升序或降序)對它們進行排序,併爲每個packageId指定一個row_number,從1開始。

所以,子查詢將返回這一點,如果它被單獨運行:

EntryId (PK) PackageId SubProductID SubProductSequence rna rnd 
3    1111   33    1     1 5 
5    1111   122    2     2 4 
1    1111   17    3     3 3 
2    1111   28    4     4 2 
4    1111   67    5     5 1 

6    2222   18    4     1 5 
7    2222   29    5     2 4 
9    2222   103    7     3 3 
8    2222   33    9     4 2 
10    2222   99    11     5 1 

15    3333   9845   1     1 5 
14    3333   1023   2     2 4 
13    3333   789    3     3 3 
11    3333   256    5     4 2  
12    3333   333    6     5 1 

WHERE條件在外部查詢增加是顯而易見的事後。

+0

謝謝 - 效果很好。我想了解*爲什麼這也適用,所以我會嘗試將其分解成其子組件以解決問題。如果你可以添加任何澄清評論,這將是偉大的。否則,謝謝你的偉大答案! – LeopardSkinPillBoxHat

+2

@LeopardSkinPillBoxHat - 將外部'select'改爲'select *'並註釋掉'where'子句。它應該變得清楚它是如何工作的。 – HABO

+0

令人敬畏的答案和描述 - 再次感謝! – LeopardSkinPillBoxHat

1

提高波希米亞的想法 -

;WITH MinMax AS 
(SELECT PackageId , 
    MIN(SubProductSequence) [Min], 
    MAX(SubProductSequence) [Max] 
FROM @TempPackages 
GROUP BY PackageId) 

SELECT EntryId, SubProductSequence, TP.PackageId, SubProductID FROM @TempPkges TP 
INNER JOIN MinMax MM ON TP.PackageId = MM.PackageId 
AND (SubProductSequence = MM.[Min] OR SubProductSequence = MM.[Max]) 

然後,你可以添加自己的ORDER BY

0
WITH t1 AS 
(SELECT PackageId,MIN(SubProductSequence) minm,MAX(SubProductSequence) maxm 
FROM #@TempPackages 
GROUPBY PackageId 
) 
SELECT pk.EntryId, pk.PackageId,pk.SubProductID, pk.SubProductSequence 
FROM #@TempPackages pk INNER JOIN t1 
ON pk.PackageId = t1.PackageId 
WHERE pk.SubProductSequence = t1.minm OR 
     pk.SubProductSequence = t1.maxm 
相關問題