从Linq-to-SQL子查询中省略重复的行集

时间:2017-03-12 21:23:43

标签: c# sql sql-server linq linq-to-sql

我正在编写一项跟踪在线射击游戏统计数据的服务。客户端向服务器报告事件,然后将事件记录在SQL Server数据库中。服务器应生成从客户端报告汇总的游戏事件报告 - 事件声明的真实性基于报告它的客户端数量。

我有一个Linq-to-SQL查询,它根据发生的时间(7秒内)对来自不同客户端的事件报告进行分组。

Events
    .Select(e => 
        Events.Where(ev =>
            // Same event type
            ev.Discriminator == e.Discriminator &&
            // Same match
            ev.ServerIpAddress == e.ServerIpAddress &&
            SqlMethods.DateDiffSecond(ev.MatchStartTime, e.MatchStartTime) < 30 &&
            // Find nearby events
            Math.Abs(ev.MatchTime.TotalSeconds - e.MatchTime.TotalSeconds) < 7 &&
            // That are duplicate
            ev.VictimTribesGuid == e.VictimTribesGuid &&
            ev.KillerTribesGuid == e.KillerTribesGuid &&
            ev.KillType == e.KillType &&
            ev.Weapon == e.Weapon
        )
    )

返回以下内容:

Result

事件按预期分组,但由于外部查询是&#34;按事件&#34;,组是重复的(请参阅前两行)。

有没有办法剥离这些重复的群组?

2 个答案:

答案 0 :(得分:1)

GroupBy似乎是适当的方法。但这并不像它看起来那么容易。这似乎是一个合理的操作:集群事件发生时。你只需要定义某种“平等”,这样你就可以将更多或更少相同的事件分组,不是吗?您在同一游戏中选择的平等定义是:相隔不到7秒

但是有一个问题类似于我所描述的here。当3个事件abc出现在0s,5s和10s时,“7s规则”定义了以下“等值”:

a ≈ b
b ≈ c

但是ab相隔10秒,所以

a !≈ c

在数学术语中,这意味着平等不是传递性的。这意味着您不能简单地将事件分组,因为它们相距不到7秒。

我认为你需要一种不同的方法。你应该开始计算游戏中第一次发生的事件。应计算此事件发生后7秒内发生的所有事件(在同一游戏中)。从7秒开始的第一个事件开始一个新的计数。这可以通过简单的foreach完成。

一个复杂的问题是,我上面说的所有内容也适用于MatchStartTime条件,您决定游戏是“平等的”。我认为你应该尝试找到一种不那么模糊的方法来建立这个事实,例如通过为游戏实例分配一个guid。否则你应该采取与事件“相等”相同的方法。

答案 1 :(得分:0)

尝试使用.Distinct();

Events
    .Select(e => 
        Events.Where(ev =>
            // Same event type
            ev.Discriminator == e.Discriminator &&
            // Same match
            ev.ServerIpAddress == e.ServerIpAddress &&
            SqlMethods.DateDiffSecond(ev.MatchStartTime, e.MatchStartTime) < 30 &&
            // Find nearby events
            Math.Abs(ev.MatchTime.TotalSeconds - e.MatchTime.TotalSeconds) < 7 &&
            // That are duplicate
            ev.VictimTribesGuid == e.VictimTribesGuid &&
            ev.KillerTribesGuid == e.KillerTribesGuid &&
            ev.KillType == e.KillType &&
            ev.Weapon == e.Weapon
        ).Distinct();
    )