2012-12-27 31 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 
相关问题