SQL - 计数和汇总(在范围内)给定事务的实例数

时间:2010-01-25 20:30:47

标签: sql sql-server tsql aggregate pivot

我有一个Occurrences表,每次用户执行操作时都包含一行。用户每天多次采取行动。它看起来像这样:

Date      Username
------    --------
1/1/9     User1
1/1/9     User1
1/1/9     User2
1/2/9     User1
1/2/9     User3
1/3/9     User1
1/3/9     User1
1/3/9     User1
1/3/9     User2
1/3/9     User3
1/4/9     User1
1/5/9     User1
1/6/9     User1
1/7/9     User1

对于该范围内的每一天,我想显示多次采取行动的人数 - 比如说,2到5次,6到10次,超过10次。但是,我考虑在另一天重复操作以计算该操作的另一个实例。例如,如果用户在第一天做了3次,然后在第二天做了任何#次,我看到用户已经完成了2次操作,因此应该在2到5次列。

对应于上述样本数据的结果集将是:

        #_of_people       #_of_people       #_of_people       
        who_did_action    who_did_action    who_did_action        
Date    2to5_times        6to10_times       more_than_10      Total
-----   --------------    --------------    --------------    -----
1/1/9   0                 0                 0                 0
1/2/9   1                 0                 0                 1
1/3/9   3                 0                 0                 3   
...    
1/7/9   0                 1                 0                 1        

请注意,结果的每一行都只计算特定日期的重复操作次数 - 不累计。

  • 1/1/9行全部为零,因为它是第一天,并且所有操作都被认为是第一天。
  • 1/2/9行是1,0,0,1,因为只有User1重复 - 这是User3的第一次。
  • 1/3/9行是3,0,0,3因为User1重复了两次,User2重复了一次,User3也重复了一次。
  • 1/7/9行是0,1,0,1,因为User1重复了6次。

2 个答案:

答案 0 :(得分:1)

我能想出最好的,未经测试的:

DECLARE @username VARCHAR(40)
DECLARE @date DATETIME
DECLARE @counter INT
    SET @counter = 1

WITH occur AS (
     SELECT DISTINCT
            CONVERT(VARCHAR(10), o.date, 101) AS dt,
            o.username
       FROM OCCURRENCES o
   ORDER BY o.username, dt),
     occur_rank AS (
     SELECT x.dt,
            @username = x.username,
            @date = CAST(x.dt AS DATETIME),
            CASE WHEN @username = x.username AND @date + 1 = x.date THEN @counter = @counter + 1 ELSE @counter = 1 END AS rank
       FROM occur x
   ORDER BY x.username, x.dt)
  SELECT or.dt,
         SUM(CASE WHEN or.rank BETWEEN 2 AND 5 THEN 1 ELSE 0 END) AS 2_to_5,
         SUM(CASE WHEN or.rank BETWEEN 6 AND 10 THEN 1 ELSE 0 END) AS 6_to_10
    FROM occur_rank or
GROUP BY or.dt

如果您可以在日期间隔重置编号,其余部分很容易。但是none of the SQL Server ranking functions support that。因此,手动递增变量。

第一个CTE,occur只返回与日期关联的用户名列表。第二个CTE建立在它的基础上,将最终输出的排名添加到枢轴上。

答案 1 :(得分:0)

我使用了带有相关子查询的派生表。

相关子查询会产生一个ActionCount列,该列计算不同日期的数量,包括该行的用户名的行日期。

生成的派生表列出了每个Date,Username和ActionCount。

外部查询然后按日期对结果进行分组,计算2到5之间,6到10之间,大于10之间的ActionCounts数,以及对于Total,大于1(ActionCount等于1不是a) '重复'。)

def get_all_last_names():
    unique_last_names = User.query.with_entities(User.last_name.distinct().label("last_name")).order_by(User.last_name.asc()).all()
    return [(user.last_name, user.last_name) for user in unique_last_names]

class UserAdmin(sqla.ModelView):

    column_filters = [
        FilterEqual(column=User.last_name, name='Last Name', options=get_all_last_names),
    ]

    # This is probably NOT the correct way to refresh the filters cache
    @expose('/')
    def index_view(self):
        self._refresh_filters_cache()
        return super(UserAdmin, self).index_view()
相关问题