如何找出最大累积和与最小累积和之和的差值?

时间:2017-05-24 05:18:38

标签: sql sql-server tsql sql-server-2012

提前谢谢。

我有一张桌子:

 id||   Subject ||   Marks

 1 ||   English ||   10

 2 ||   Maths   ||   30

 3 ||   History ||   50

 4 ||   English ||   70

 5 ||   Maths   ||   80

 6 ||   History ||   90

 7 ||   English ||   100

 8 ||   Maths   ||   130

 9 ||   History ||   150  

我想找出每个主题的最大累积金额和最小累计金额之和的差异:

实施例

Subject ||   Marks  ||   Cumulative sum    ||  Cumulative diff(max-min)

history ||    50    ||   50                ||

History ||    90    ||   140               || 

History ||    150   ||   290               || (290-50)=240

我可以获得累积金额但无法找到其余值:

 select t1.id,t1.marks,sum(t2.marks) as sum1
 from [NorthWind].[dbo].[Table_1] t1
 inner join [NorthWind].[dbo].[Table_1] t2 on t1.id>=t2.id
 group by t1.id,t1.marks
 order by t1.id 

谢谢。

4 个答案:

答案 0 :(得分:2)

试试这个

Rextester sample

with tbl1 as (
select t.*
,sum(marks) over (partition by subject order by id) as cum_sum
,sum(marks) over (partition by subject order by id) 
- min(marks) over (partition by subject order by id) 
    as diff
,row_number() over (partition by subject order by id desc) as rnk
from your_table t
)
select 
id,Subject,Marks,cum_sum
,case when rnk=1 then diff else null end as cum_diff
from tbl1 t
order by subject,id;

输出:

+----+---------+-------+---------+----------+
| id | Subject | Marks | cum_sum | cum_diff |
+----+---------+-------+---------+----------+
|  1 | English |    10 |      10 | NULL     |
|  4 | English |    70 |      80 | NULL     |
|  7 | English |   100 |     180 | 170      |
|  3 | History |    50 |      50 | NULL     |
|  6 | History |    90 |     140 | NULL     |
|  9 | History |   150 |     290 | 240      |
|  2 | Maths   |    30 |      30 | NULL     |
|  5 | Maths   |    80 |     110 | NULL     |
|  8 | Maths   |   130 |     240 | 210      |
+----+---------+-------+---------+----------+

答案 1 :(得分:1)

使用窗口函数尝试此操作。

您可以使用窗口总和来查找cuml sum,然后使用max和min。

android {
    compileSdkVersion 23
    buildToolsVersion "23.0.0"

    defaultConfig {
        applicationId "com.google.android.apps.watchme"
        minSdkVersion 16
        targetSdkVersion 23
        versionCode 1
        versionName "1.0"
    }

    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
    }
    sourceSets {
        main {
            jni.srcDirs = []
        }
    }

}

dependencies {
    compile fileTree(dir: 'libs', include: ['*.jar'])
    compile 'com.google.android.gms:play-services-plus:7.8.0'
    compile 'com.android.support:support-v4:23.0.0'
    compile 'com.android.support:design:23.0.0'
    compile 'com.google.apis:google-api-services-youtube:v3-rev120-1.19.0'
    compile 'com.google.http-client:google-http-client-android:+'
    compile 'com.google.api-client:google-api-client-android:+'
    compile 'com.google.api-client:google-api-client-gson:+'
    compile 'com.mcxiaoke.volley:library:1.0.18'
    compile 'com.google.code.gson:gson:2.3'
}

答案 2 :(得分:1)

您可以像这样使用SUM() OVER()

 DECLARE @SampleData AS TABLE
 (
    Id int,
    Subject varchar(20),
    Marks int
 )

 INSERT INTO @SampleData
 VALUES 
( 1, 'English', 10),
( 2, 'Maths',   30),
( 3, 'History', 50),
( 4, 'English', 70),
( 5, 'Maths',   80),
( 6, 'History', 90),
( 7, 'English', 100),
( 8, 'Maths',   130),
( 9, 'History', 150 )

SELECT  *, 
       sum(sd.Marks) OVER(PARTITION BY sd.Subject ORDER BY sd.Id) AS [Cumulative sum],
       sum(sd.Marks) OVER(PARTITION BY sd.Subject) - FIRST_VALUE(sd.Marks) OVER(PARTITION BY sd.Subject ORDER BY sd.Id) AS [Cumulative diff(max-min)] 
                                                   -- or try MIN(sd.Marks).....
FROM @SampleData sd
ORDER BY sd.Subject, sd.Id

演示链接:http://rextester.com/GAE89325

答案 3 :(得分:1)

DECLARE @TempData AS TABLE
 (
    Id int,
    Subject varchar(20),
    Marks int
 )
 INSERT INTO @TempData
 VALUES 
( 1, 'English', 10),
( 2, 'Maths',   30),
( 3, 'History', 50),
( 4, 'English', 70),
( 5, 'Maths',   80),
( 6, 'History', 90),
( 7, 'English', 100),
( 8, 'Maths',   130),
( 9, 'History', 150 )

Declare @SelectSubject Varchar(20)='History' --SELECT your subject here like English,Maths,History

SELECT Subject
    ,Marks
    ,RunningTotal AS CumulativeSum
    ,CASE 
        WHEN Rno = 3
            THEN Cumulativediff
        ELSE ''
        END AS Cumulativediff
FROM (
    SELECT *
        ,  (
            MAX(RunningTotal) OVER (ORDER BY Subject)) - (MIN(RunningTotal) OVER (ORDER BY Subject)
            ) AS Cumulativediff
        ,ROW_NUMBER() OVER (ORDER BY (SELECT 1)) AS Rno
    FROM (
        SELECT *
        FROM (
            SELECT ISNULL(Subject, 'GrandTotal') AS Subject
                ,ISNULL(CASt(Marks AS VARCHAR(10)), 'SubTotal') AS Marks
                ,SUM(Marks) OVER (
                    PARTITION BY Subject ORDER BY Id
                    ) AS RunningTotal
            FROM @TempData
            ) Dt
        WHERE dt.Subject = @SelectSubject
        ) Dt2
    ) Final

结果:

Subject Marks   CumulativeSum   Cumulativediff
-----------------------------------------------
History 50       50             0
History 90       140            0
History 150      290            240