基于列

时间:2017-09-07 11:11:02

标签: sql sql-server sql-server-2016

我有一个像这样的值的表:

enter image description here

我希望得到基于IDyear的累积总和,因此它应该返回这样的输出,即对于id-1和2010年,记录的总和将是2。                             id-2和2010年的记录总和将为1和                              id-2和2011年将是1 + 1 = 2,即我要求每个id的运行总计按升序排列。

同样,对于id = 3,Sum将为1,因为id 4将基于年份为1。对于5年,对于2014年将是3,对于2015年它将是计数前一年的总和+计数当前的总和yr,即它将是3 + 1 = 4并且对于2016年它将是3 + 1 + 1 = 5。因此,要做什么。有人可以帮忙吗?

enter image description here

3 个答案:

答案 0 :(得分:1)

有很多方法可以做到这一点。以下是其中一个,内部查询:

create table #table_name
(
    UserID int,
    Year int
)
INSERT INTO #table_name (UserID, Year)
VALUES
    (1, 2010)
    ,(1,2010)
    ,(2,2010)
    ,(2,2011)
    ,(3,2012)
    ,(4,2013)
    ,(5,2014)
    ,(5,2014)
    ,(5,2014)
    ,(5,2015)
    ,(5,2016)

SELECT 
    UserID
    ,YEAR
    ,(SELECT COUNT(Year) FROM #table_name WHERE Year <= tt.Year AND UserID = tt.UserID)
FROM 
    #table_name AS tt
GROUP BY UserID, Year

你也可以使用row number over(编辑:请参阅下面这个技巧的答案,我认为这对于这么简单的任务来说有点太复杂了)。上面的查询返回您所需的输出

+--------+------+-------+
| UserID | Year | COUNT |
+--------+------+-------+
|      1 | 2010 |     2 |
|      2 | 2010 |     1 |
|      2 | 2011 |     2 |
|      3 | 2012 |     1 |
|      4 | 2013 |     1 |
|      5 | 2014 |     3 |
|      5 | 2015 |     4 |
|      5 | 2016 |     5 |
+--------+------+-------+

答案 1 :(得分:1)

这比我想要的更加嵌套,我觉得有一种更好的方法可以做到这一点,可能只有一个窗口功能,但我不能通过没有一个独特的数据行。

SELECT id,
year ,sum(c) OVER (
    PARTITION BY id ORDER BY year rows unbounded preceding
    )
FROM (
SELECT id,
    year,
    count(rn) c
FROM (
    SELECT id,
        year,
        row_number() OVER (
            ORDER BY year
            ) AS rn
    FROM your_table -- you will need to change this to your table
    ) a
GROUP BY id,
    year
) a

我们所做的是首先使用行号构建数据,所以现在一切都是唯一的,然后我们对该唯一的行号进行计数,然后执行windows函数来按年计算行数。

答案 2 :(得分:1)

不需要让思考比他们需要的更复杂......

IF OBJECT_ID('tempdb..#TestData', 'U') IS NOT NULL 
DROP TABLE #TestData;

CREATE TABLE #TestData (
    ID INT NOT NULL,
    [Year] INT NOT NULL 
    );
INSERT #TestData (ID, Year) VALUES
    (1, 2010), (1, 2010), (2, 2010), (2, 2011), 
    (3, 2012), (4, 2013), (5, 2014), (5, 2014),
    (5, 2014), (5, 2015), (5, 2016);

--=======================================

SELECT
    tdg.ID,
    tdg.Year,
    RunningCount = SUM(tdg.Cnt) OVER (PARTITION BY tdg.ID ORDER BY tdg.Year ROWS UNBOUNDED PRECEDING)
FROM (   
    SELECT td.ID, td.Year, Cnt = COUNT(1)
    FROM #TestData td
    GROUP BY td.ID, td.Year
    ) tdg;

结果...

ID          Year        RunningCount
----------- ----------- ------------
1           2010        2
2           2010        1
2           2011        2
3           2012        1
4           2013        1
5           2014        3
5           2015        4
5           2016        5