分组检索4个值

时间:2012-04-18 11:42:55

标签: sql sql-server group-by aggregate-functions

我有以下查询

SELECT  Cod ,
        MIN(Id) AS id_Min,
        -- retrieve value min in the middle as id_Min_Middle,
        -- retrieve value max in the middle as id_Max_Middle,
        MAX(Id) AS id_Max,            
        COUNT(*) AS Tot
FROM    Table a ( NOLOCK )        
GROUP BY Cod
HAVING  COUNT(*)=4

我如何检索minmax之间的值,就像我为minmax所做的那样? 如果我使用(SUM(Id) - (MIN(Id)+MAX(Id)),我会获得summiddle min的{​​{1}},但不会获得我想要的值。

实施例

max

必需的输出

Cod      |  Id

Stack       10
Stack       15
Stack       11
Stack       40
Overflow    1
Overflow    120
Overflow    15
Overflow    100

4 个答案:

答案 0 :(得分:1)

我不确定标记为plsql sql-server的问题意味着什么。但我假设您正在使用支持CTE和窗口函数的数据库系统。

要概括您尝试做的事情,首先将行号分配给行,然后使用您想要实现轴的任何技术:

;WITH OrderedValues as (
    SELECT Cod,Id,ROW_NUMBER() OVER (PARTITION BY Cod ORDER BY Id) as rn
       COUNT(*) OVER (PARTITION BY Cod) as Cnt
    FROM Table (NOLOCK)
), With4Values as (
    SELECT * from OrderedValues where Cnt=4
)
SELECT Cod,
    --However you want to do the pivot. Here I'll use MAX/CASE
    MAX(CASE WHEN rn=1 THEN Id END) as Value1,
    MAX(CASE WHEN rn=2 THEN Id END) as Value2,
    MAX(CASE WHEN rn=3 THEN Id END) as Value3,
    MAX(CASE WHEN rn=4 THEN Id END) as Value4
FROM
    With4Values
GROUP BY
    Cod

您可以希望看到这更容易扩展到更多列,而不是回答有关3行或4行的过于具体的问题。但是,如果您需要处理任意数量的列,则必须切换到动态SQL。

答案 1 :(得分:1)

尝试使用此功能,祝您好运

WITH temp AS
         (SELECT   cod, MIN (ID) min_id, MAX (ID) max_id
              FROM tab
          GROUP BY cod
            HAVING COUNT (ID) = 4)
    SELECT code, temp.min_id,
           (SELECT   MIN (ID)
                FROM tab
               WHERE cod = temp.cod AND ID NOT IN (temp.min_id)
            GROUP BY cod) min_mid_id,
           (SELECT   MAX (ID)
                FROM tab
               WHERE cod = temp.cod AND ID NOT IN (temp.max_id)
            GROUP BY cod) max_min_id, temp.max_id
      FROM temp;

答案 2 :(得分:1)

只有一个[Table|[Clustered] Index]]Scan(演示here):

SELECT  pvt.Cod,
        pvt.[1] AS MinValue,
        pvt.[2] AS MinInterValue,
        pvt.[3] AS MaxInterValue,
        pvt.[4] AS MaxValue
FROM
(
        SELECT  x.Cod, x.ID, x.RowNumAsc
        FROM
        (
                SELECT  *,
                        ROW_NUMBER() OVER(PARTITION BY t.Cod ORDER BY t.ID ASC) RowNumAsc,
                        ROW_NUMBER() OVER(PARTITION BY t.Cod ORDER BY t.ID DESC) RowNumDesc
                FROM    MyTable t
        ) x
        WHERE   x.RowNumAsc = 1 AND x.RowNumDesc = 4
        OR      x.RowNumAsc = 2 AND x.RowNumDesc = 3
        OR      x.RowNumAsc = 3 AND x.RowNumDesc = 2
        OR      x.RowNumAsc = 4 AND x.RowNumDesc = 1

) y
PIVOT   ( MAX(y.ID) FOR y.RowNumAsc IN ([1], [2], [3], [4]) ) pvt;

答案 3 :(得分:0)

我知道你想要排除极值并找到其余的最小值和最大值。 这就是我的想法,但我没有机会跑去测试它......

WITH Extremes AS ( SELECT Cod, MAX(ID) AS Id_Max, MIN(ID) AS Id_Min 
                    FROM [Table] a GROUP BY Cod)
SELECT 
  e.Cod,
  e.Id_Min,
  MIN(a.Id) AS id_Min_Middle,
  MAX(a.Id) AS id_Max_Middle,
  e.Id_Max
FROM Extremes e
LEFT JOIN [Table] a ON a.Cod = e.Cod AND a.Id > e.Id_Min AND a.Id < e.Id_Max
GROUP BY e.Cod