【发布时间】:2018-07-25 17:49:18
【问题描述】:
我试图找到一个SQL 唯一的解决方案来解决与计算连续活动出席率相关的问题。这些事件发生在不同的日子,所以我不能使用任何顺序日期方法来确定连续出席。要计算一个人的连续出席率,我会从最近的事件开始,然后按时回溯。我会计算该人参加的每个活动,当我遇到该人未参加的活动时,我会停下来。这使我可以计算最近连续参加的活动。目前,所有数据都托管在SQL 表中,以下是包含数据的示例模式:
USERS
ID UserName MinutesWatched
--- -------- --------------
1 jdoe 30
2 ssmith 400
3 bbaker 350
4 tduke 285
EVENTS
ID Name StartDate
-- ----------- ---------
1 1st Event 07/15/2018
2 2nd Event 07/16/2018
3 3rd Event 07/18/2018
4 4th Event 07/20/2018
ATTENDANCE
ID User_ID Event_ID
-- ------- --------
1 1 1
2 1 2
3 1 3
4 1 4
5 2 4
6 2 3
7 3 4
8 3 2
9 3 1
10 4 4
11 4 3
12 4 2
对于我想要得到的输出:
OUTPUT
User_ID Consecutive WatchedMinutes
------- ----------- --------------
1 4 30
2 2 400
3 1 350
4 3 285
我已经构建了 C# 代码以迭代方式执行此操作,但是当我处理 300,000 多个用户和数百个事件时它会很慢。我很想看到这个的SQL 版本。
以下是根据 Dan 的要求计算热门活动观众的方法。输出实际上只是一个列出 Top X 事件查看器的字符串。
public string GetUsersTopWatchedConsecutiveStreams(int topUserCount)
{
string results = "Top " + topUserCount + " consecutive viewers - ";
Dictionary<ChatUser, int> userinfo = new Dictionary<ChatUser, int>();
using (StorageModelContext db = new StorageModelContext())
{
IQueryable<ChatUser> allUsers = null;
if (mainViewModel.CurrentStream != null)
allUsers = db.ViewerHistory.Include("Stream").Include("User").Where(x => x.Stream.Id == mainViewModel.CurrentStream.Id).Select(x => x.User);
else
allUsers = db.ViewerHistory.Include("Stream").Include("User").Where(x => x.Stream.Id == (db.StreamHistory.OrderByDescending(s => s.StreamEnd).FirstOrDefault().Id)).Select(x => x.User);
foreach (var u in allUsers)
{
int totalStreams = 0;
var user = db.Users.Include("History").Where(x => x.UserName == u.UserName).FirstOrDefault();
if (user != null)
{
var streams = user.History;
if (streams != null)
{
var allStreams = db.StreamHistory.OrderByDescending(x => x.StreamStart);
foreach (var s in allStreams)
{
var vs = streams.Where(x => x.Stream == s);
if (vs.Count() > 0)
totalStreams++;
else
break;
}
}
}
userinfo.Add(u, totalStreams);
totalStreams = 0;
}
var top = userinfo.OrderByDescending(x => x.Value).ThenByDescending(x => x.Key.MinutesWatched).Take(topUserCount);
int cnt = 1;
foreach (var t in top)
{
results += "#" + cnt + ": " + t.Key + "(" + t.Value.ToString() + "), ";
cnt++;
}
if (cnt > 1)
results = results.Substring(0, results.Length - 2);
}
return results;
}
当没有活动正在运行时,mainViewModel.CurrentStream 为 null。当直播事件发生时,它将包含一个对象,其中包含与直播事件相关的信息。
【问题讨论】:
-
用您正在使用的数据库标记您的问题。
-
"我已经构建了 C# 代码来执行此操作" 它必须是透明墨水,因为我看不到它。
-
戈登 - 完成。谢谢
-
Dan - 我最初没有包含代码,因为我认为它不会增加太多价值。我已经用信息更新了帖子。
标签: c# sql sql-server