SQL Aggregation用于较小的结果集

时间:2009-10-06 19:37:38

标签: sql sql-server database tsql

我有一个数据库,我需要将记录聚合到另一个较小的集合中。此结果集应包含原始记录的特定列的最大值和最小值之间的差异,它们加起来为某个SUM,一个闭合的间隔常数C.

常量C确定如何聚合原始记录,并且结果集中的任何条目都不会超过它。当然,我应该以自然主键顺序运行它。

举例说明:表格有:

  • [键]
  • 并[a]
  • 并[b]
  • [minColumn]
  • [maxColumn]
  • [N]

...都是int数据类型。

我在一个结果集之后,其中包含该组的MAX(maxColumn) - MIN(minColumn)条目,当它们的差值总和时,它小于或等于常数C.

除了MAX(maxColumn)和MIN(minColumn)值之外,在此结果集中创建新条目之前,我还需要FIRST记录列[a]和LAST记录列[b]值。最后,对于组中的所有原始记录,N列应该是SUMmed。

有没有游标的有效方法吗?

----- [Trivial Sample] -------------------------------------- ----------------------

我试图通过一个稍微复杂的运行总和,常数C.

进行分组

只有一个表,列都是int类型和样本数据

declare @t table (
  PK int primary key
    , int a, int b, int minColumn, int maxColumn, int N 
)

insert @t values (1,5,6,100,200,1000)
insert @t values (2,7,8,210,300,2000)
insert @t values (3,9,10,420,600,3000)
insert @t values (4,11,12,640,800,4000)

因此:

key, a,   b, minColumn, maxColumn,    N
---------------------------------------
1,   5,   6,       100,       200, 1000 
2,   7,   8,       210,       300, 2000 
3,   9,  10,       420,       600, 3000 
4,   11, 12,       640,       800, 4000 

我需要结果集看起来像,对于常数C为210:

firstA | lastB | MIN_minColumn | MAX_maxColumn | SUM_N
5       8                  100             300    3000 
9       10                 420             600    3000 
11      12                 640             800    4000 

[添加下面讨论的赏金和样本]

对于C = 381,它应包含2行:

firstA | lastB | MIN_minColumn | MAX_maxColumn | SUM_N
5            8             100             300    3000 
9           12             420             800    7000

希望这能更好地证明问题..对于常数C表示1000,你会得到1条记录:

firstA | lastB | MIN_minColumn | MAX_maxColumn | SUM_N
5           12             100             800   10000

3 个答案:

答案 0 :(得分:2)

DECLARE @c int
SELECT @c = 210

SELECT MIN(a) firstA,
       MAX(b) lastB, 
       MIN(minColumn) MIN_minColumn, 
       MAX(maxColumn) MAX_maxColumn, 
       SUM(N) SUM_N
FROM @t t 
JOIN (SELECT key, floor(sum/@c) as rank
        FROM (SELECT key, 
                     (SELECT SUM(t2.maxColumn - t2.minColumn) 
                        FROM @t t2 
                       WHERE t2.key <= t1.key 
                    GROUP BY t1.key) as sum
               FROM @t t1) A
     ) B on B.key = t.key
GROUP BY B.rank

/*

Table A: for each key, calculating SUM[maxColumn-minColumn] of all keys below it.
Table B: for each key, using the sum in A, calculating a rank so that:
  sum = (rank + y)*@c where 0 <= y < 1. 
  ex: @c=210, rank(100) = 0, rank(200) = 0, rank(220) = 1, ...
finally grouping by rank, you'll have what you want.

*/

答案 1 :(得分:1)

宣布@c int

选择@c = 210

选择firstA = min(a),lastB = max(b),MIN_minColumn = min(minColumn),MAX_maxColumn = max(maxColumn),SUM_N = sum(N) 从T minColumn&lt; = @c

联合所有

选择a,b,minColumn,maxColumn,N 从T 其中minColumn&gt; @c

答案 2 :(得分:1)

我对你想要产生的结果的分组逻辑感到有点困惑,但是根据你所寻找的描述,我认为你需要一个HAVING子句。您应该可以执行以下操作:

SELECT groupingA, groupingB, MAX(a) - MIN(b)
FROM ...
GROUP BY groupingA, groupingB
HAVING (MAX(a) - MIN(b)) < C

...为了过滤掉你的最大值和最小值之间的差异,一旦你确定了你的分组。希望这有用