2016-11-14 19 views
1

テーブル上の条件で部分和を計算する方法を理解しようとしています。SQL:条件付きパーティション内の合計

私は、このテーブルをしました:そう

Id part value TimeValue 
1 part1 50  15 
2 part1 8  12 
3 part1 12  9 
4 part1 10  20 
5 part2 6  4 
6 part2 9  15 

CREATE TABLE [dbo].[test](
    [Id] [int] NOT NULL, 
    [part] [varchar](50) NULL, 
    [value] [int] NULL, 
    [TimeValue] [int] NULL, 
CONSTRAINT [PK_test] PRIMARY KEY CLUSTERED 
(
    [Id] ASC 
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY] 
) ON [PRIMARY] 

GO 
SET ANSI_PADDING OFF 
GO 
INSERT [dbo].[test] ([Id], [part], [value], [TimeValue]) VALUES (1, N'part1', 50, 15) 
GO 
INSERT [dbo].[test] ([Id], [part], [value], [TimeValue]) VALUES (2, N'part1', 8, 12) 
GO 
INSERT [dbo].[test] ([Id], [part], [value], [TimeValue]) VALUES (3, N'part1', 12, 9) 
GO 
INSERT [dbo].[test] ([Id], [part], [value], [TimeValue]) VALUES (4, N'part1', 10, 20) 
GO 
INSERT [dbo].[test] ([Id], [part], [value], [TimeValue]) VALUES (5, N'part2', 6, 4) 
GO 
INSERT [dbo].[test] ([Id], [part], [value], [TimeValue]) VALUES (6, N'part2', 9, 15) 
GO 

と私はTimeValue AS INT<=of current row TimeValue

カラム part AS VARCHAR(50)のパーティション上の合計と列 pSum AS INTを追加するために選択を書くshoud

私はこれを書いています:

自然になっ
SELECT *, SUM(value) OVER (PARTITION BY part) AS pSum FROM test 

:すべてのパーティション全体に

Id part value TimeValue pSum 
1 part1 50   15  80 
2 part1 8   12  80 
3 part1 12   9  80 
4 part1 10   20  80 
5 part2 6   4  15 
6 part2 9   15  15 

が、このメイク合計を、私はこれを取得するためのTimeValue条件を検討する必要があります。

Id part value TimeValue pSum 
1 part1 50  15   70  (sum in part1 where TimeValue <= 15 : 12 + 8 + 50) 
2 part1 8  12   20  (sum in part1 where TimeValue <= 12 : 12 + 8) 
3 part1 12  9   12  (sum in part1 where TimeValue <= 9 : just 12) 
4 part1 10  20   80  (sum in part1 where TimeValue <= 20 : 12 + 8 + 50) 
5 part2 6  4   6  (sum in part2 where TimeValue <= 4 : just 6) 
6 part2 9  15   15  (sum in part2 where TimeValue <= 15 : 9 + 6) 

私はSQLのための可能な解決策を読みました2012年のソリューションhere

SUM(value) OVER (PARTITION BY part ORDER BY TimeValue rows between unbounded preceding and current row) AS pSum 

SQL 2008を使用して

助けてください。 ありがとうございます。

答えて

2

SQL Server 2008では、これを行うための効率的な方法はありません。 1つの方法では、outer applyを使用します。

select t.*, v.cumesum 
from test t outer apply 
    (select sum(t2.value) 
     from test t2 
     where t2.part = t.part and t2.timevalue <= t.timevalue 
    ) v(cumesum); 
+1

誰かが私にほほえみをするよう提案しても、あなたのソリューションは本当に優れています。 – user2595496

+1

@ user2595496それは議論の余地があります。小さなデータセットの場合は、 'CROSS/OUTER APPLY'を使用して取り除くことができます。大規模なデータセットの場合は、カーソルを使用する方がよいでしょう。 'APPLY'を使用するメソッドがO(n^2)で、カーソル(またはループ)メソッドがO(n)であるとします。 –

+0

@TT。 。 。 。 'APPLY'を使う方法は必要ありません* O(n^2)。さらに、 'test(part、timevalue)'のインデックスを利用することもできます。それは、多くの状況下では、 'WHILE'ループを使うほうが良いかもしれないと言いました。しかし、データ全体のサイズに基づいているわけではありません。与えられた '部分 'の最大行数とインデックスの有無に基づいています。 –