如何计算SQL Server中序列中组的最小值和最大值?

时间:2016-01-16 18:49:28

标签: sql sql-server group-by gaps-and-islands

我在SQL Server的数据库表中有以下数据:

MIMMAXPOINTS

Val_B列实际上应包含最低Vector'BELOW'Val_A,最高Vector'ABOVE'MINMAXPOINTS }}。因此,我们在MINMAXPOINTS 68.40 68.40 82.40 82.40 82.40 82.40 72.29 81.75 81.75 81.75 中有以下值:

In [32]: import numpy as np 

In [33]: list_of_arrays = list(map(lambda x: x * np.ones(2), range(5)))

In [34]: list_of_arrays
Out[34]: 
[array([ 0.,  0.]),
 array([ 1.,  1.]),
 array([ 2.,  2.]),
 array([ 3.,  3.]),
 array([ 4.,  4.])]

In [37]: shape = list(list_of_arrays[0].shape)

In [38]: shape
Out[38]: [2]

In [39]: shape[:0] = [len(list_of_arrays)]

In [40]: shape
Out[40]: [5, 2]

In [41]: arr = np.concatenate(list_of_arrays).reshape(shape)

In [42]: arr
Out[42]: 
array([[ 0.,  0.],
       [ 1.,  1.],
       [ 2.,  2.],
       [ 3.,  3.],
       [ 4.,  4.]])

没有光标可以吗?

任何帮助将不胜感激!。

3 个答案:

答案 0 :(得分:1)

首先应用经典gaps-and-islands来确定组(差距/岛/上/下),然后为每个组计算MINMAX

我假设ID列定义了行的顺序。

在SQL Server 2008上测试。这是SQL Fiddle

示例数据

DECLARE @T TABLE
([Id] int, [dt] date, [Val_A] float, [Val_B] float, [Val_C] float, [Avg] float, 
[Vector] varchar(5));

INSERT INTO @T ([Id], [dt], [Val_A], [Val_B], [Val_C], [Avg], [Vector]) VALUES
(329, '2016-01-15', 78.09, 68.40, 70.29, 76.50, 'BELOW'),
(328, '2016-01-14', 79.79, 75.40, 76.65, 76.67, 'BELOW'),
(327, '2016-01-13', 81.15, 74.59, 79.00, 76.44, 'ABOVE'),
(326, '2016-01-12', 81.95, 77.04, 78.95, 76.04, 'ABOVE'),
(325, '2016-01-11', 82.40, 73.65, 81.34, 75.47, 'ABOVE'),
(324, '2016-01-08', 78.75, 73.40, 77.20, 74.47, 'ABOVE'),
(323, '2016-01-07', 76.40, 72.29, 72.95, 73.74, 'BELOW'),
(322, '2016-01-06', 81.25, 77.70, 78.34, 73.12, 'ABOVE'),
(321, '2016-01-05', 81.75, 76.34, 80.54, 72.08, 'ABOVE'),
(320, '2016-01-04', 80.95, 75.15, 76.29, 70.86, 'ABOVE');

<强>查询

更好地了解它的工作原理,检查每个CTE的结果。

CTE_RowNumbers计算两个行号序列。

CTE_Groups为每个组分配一个号码(上/下)。

CTE_MinMax为每个小组计算MIN/MAX

最终SELECT选择MINMAX返回。

WITH
CTE_RowNumbers
AS
(
    SELECT [Id], [dt], [Val_A], [Val_B], [Val_C], [Avg], [Vector]
        ,ROW_NUMBER() OVER (ORDER BY ID DESC) AS rn1
        ,ROW_NUMBER() OVER (PARTITION BY Vector ORDER BY ID DESC) AS rn2
    FROM @T
)
,CTE_Groups
AS
(
    SELECT [Id], [dt], [Val_A], [Val_B], [Val_C], [Avg], [Vector]
        ,rn1-rn2 AS Groups
    FROM CTE_RowNumbers
)
,CTE_MinMax
AS
(
    SELECT [Id], [dt], [Val_A], [Val_B], [Val_C], [Avg], [Vector]
        ,MAX(Val_A) OVER(PARTITION BY Groups) AS MaxA
        ,MIN(Val_B) OVER(PARTITION BY Groups) AS MinB
    FROM CTE_Groups
)
SELECT [Id], [dt], [Val_A], [Val_B], [Val_C], [Avg], [Vector]
    ,CASE 
        WHEN [Vector] = 'BELOW' THEN MinB
        WHEN [Vector] = 'ABOVE' THEN MaxA
    END AS MINMAXPOINTS
FROM CTE_MinMax
ORDER BY ID DESC;

<强>结果

+-----+------------+-------+-------+-------+-------+--------+--------------+
| Id  |     dt     | Val_A | Val_B | Val_C |  Avg  | Vector | MINMAXPOINTS |
+-----+------------+-------+-------+-------+-------+--------+--------------+
| 329 | 2016-01-15 | 78.09 | 68.4  | 70.29 | 76.5  | BELOW  | 68.4         |
| 328 | 2016-01-14 | 79.79 | 75.4  | 76.65 | 76.67 | BELOW  | 68.4         |
| 327 | 2016-01-13 | 81.15 | 74.59 | 79    | 76.44 | ABOVE  | 82.4         |
| 326 | 2016-01-12 | 81.95 | 77.04 | 78.95 | 76.04 | ABOVE  | 82.4         |
| 325 | 2016-01-11 | 82.4  | 73.65 | 81.34 | 75.47 | ABOVE  | 82.4         |
| 324 | 2016-01-08 | 78.75 | 73.4  | 77.2  | 74.47 | ABOVE  | 82.4         |
| 323 | 2016-01-07 | 76.4  | 72.29 | 72.95 | 73.74 | BELOW  | 72.29        |
| 322 | 2016-01-06 | 81.25 | 77.7  | 78.34 | 73.12 | ABOVE  | 81.75        |
| 321 | 2016-01-05 | 81.75 | 76.34 | 80.54 | 72.08 | ABOVE  | 81.75        |
| 320 | 2016-01-04 | 80.95 | 75.15 | 76.29 | 70.86 | ABOVE  | 81.75        |
+-----+------------+-------+-------+-------+-------+--------+--------------+

答案 1 :(得分:0)

您可以使用以下查询使用案例陈述,您可以根据每行的向量值选择条件值。

查询

SELECT ID, DATE, VAL_A, VAL_B, VAL_C, AVG, VECTOR, 
CASE
    WHEN VECTOR = 'BELOW' THEN (SELECT MIN(VAL_B) FROM TABLE A)
    WHEN VECTOR = 'ABOVE' THEN (SELECT MAX(VAL_A) FROM TABLE A)
END AS MINMAXVALUE
FROM TABLE B
GO

检查这是否对您有帮助。

答案 2 :(得分:0)

修改查询以检查大于当前记录的数据组 您可以使用以下查询使用案例陈述,您可以根据每行的矢量值选择条件值。

查询

SELECT ID, DATE, VAL_A, VAL_B, VAL_C, AVG, VECTOR,
  CASE
    WHEN VECTOR = 'BELOW' THEN (SELECT MIN(VAL_B) FROM TABLE A WHERE ROWID >= B.ROWID)
    WHEN VECTOR = 'ABOVE' THEN (SELECT MAX(VAL_A) FROM TABLE A WHERE ROWID >= B.ROWID)
   END AS MINMAXVALUE

FROM TABLE B 
GO

检查这应该产生您期望从数据中获得的结果。