具有复杂where子句的复杂LINQ查询

时间:2017-05-11 01:44:35

标签: c# sql asp.net-mvc linq

首先,抱歉,如果此问题的名称不够具有描述性。我不确定该怎么命名。我有两张桌子,

Games
int GameId,
int HomeTeamId,
string HomeTeamName,
int HomeTeamScore,
int AwayTeamId,
int AwayTeamScore,
string AwayTeamName

PlayersInGame
int GameId,
int PlayerId,
string PlayerName,
string TeamName,
int TeamId

我想要做的是查询这两个表,结果如下

ViewModel
string PlayerName,
string Teams,
int GameCount,
int NumberOfWins

我的问题是我多年来一直在查询游戏,因此玩家可以为多个团队效力,在这种情况下我希望它看起来像这样

Team1/Team2/...

团队名称以/分隔。 另一个问题是,我想获得玩家参与的游戏总数,但也想出他的胜利记录。找出他的胜利记录的唯一方法是将HomeTeamScore与AwayTeamScore进行比较,并检查玩家的TeamId与获胜的团队ID。

我想知道这里最好的方法是什么?我怀疑用一个查询有办法做到这一点吗?

2 个答案:

答案 0 :(得分:2)

我假设(通过查看PlayerId)你还有一个你没有指定的Player类/表。

让我们从让所有玩家开始:

IEnumerable<Player> players = _db.Players;

我们需要将每位玩家映射到ViewModel,因此我们将使用Select

IEnumerable<ViewModel> models = players.Select(p => new ViewModel());

但是这些ViewModel个实例只是空的,我们需要填写适当的数据,让我们从最简单的数据开始,即玩家的名字:

IEnumerable<ViewModel> models = players.Select(p => new ViewModel()
{
    PlayerName = p.PlayerName
});

接下来,我们需要获取玩家参与的所有团队。为此,我们将查询PlayersInGame表并使用Where按玩家的ID过滤掉。我们还会将每个结果映射到TeamName并对其进行格式化。

IEnumerable<ViewModel> models = players.Select(p => new ViewModel()
{
    PlayerName = p.PlayerName,
    Teams = String.Join("/", _db.PlayersInGame.Where(pg => pg.PlayerId == p.PlayerId).Select(pg => pg.TeamName))
});

现在我们需要计算游戏数量,我们将再次阅读PlayersInGame,但现在我们将使用Count方法:

IEnumerable<ViewModel> models = players.Select(p => new ViewModel()
{
    PlayerName = p.Name,
    Teams = String.Join("/", _db.PlayersInGame.Where(pg => pg.PlayerId == p.Id).Select(pg => pg.TeamName)),
    GameCount = _db.PlayersInGame.Count(pg => pg.PlayerId == p.Id)
});

现在,在最后一部分,我们需要计算玩家赢了多少次,所以我们只需要查询玩家的游戏然后计算他/她赢了多少。最棘手的部分可能是确定球员是在主队还是客队。

IEnumerable<ViewModel> models = players.Select(p => new ViewModel()
{
    PlayerName = p.PlayerName,
    Teams = String.Join("/", _db.PlayersInGame.Where(pg => pg.PlayerId == p.PlayerId).Select(pg => pg.TeamName)),
    GameCount = _db.PlayersInGame.Count(pg => pg.PlayerId == p.PlayerId),
    NumberOfWins = _db.PlayersInGame.Where(pg => pg.PlayerId == p.PlayerId).Count(pg =>
    {
        Game g = _db.Games.Single(g => g.GameId == pg.GameId);
        bool isHome = g.HomeTeamId == pg.TeamId;
        return isHome ? (g.HomeTeamScore > g.AwayTeamScore) : (g.AwayTeamScore > g.HomeTeamScore);
    })
});

最终结果:

IEnumerable<ViewModel> models = _db.Players.Select(p => new ViewModel()
{
    PlayerName = p.PlayerName,
    Teams = String.Join("/", _db.PlayersInGame.Where(pg => pg.PlayerId == p.PlayerId).Select(pg => pg.TeamName)),
    GameCount = _db.PlayersInGame.Count(pg => pg.PlayerId == p.PlayerId),
    NumberOfWins = _db.PlayersInGame.Where(pg => pg.PlayerId == p.PlayerId).Count(pg =>
    {
        Game game = _db.Games.Single(g => g.GameId == pg.GameId);
        bool isHome = game.HomeTeamId == pg.TeamId;
        return isHome ? (game.HomeTeamScore > game.AwayTeamScore) : (game.AwayTeamScore > game.HomeTeamScore);
    })
});

答案 1 :(得分:0)

它非常复杂,试着参考这篇文章。因此,在TeamsGameCountNumberOfWin字段中,我再次执行查询以获取每个值并将其放入变量结果中,然后您可以将其分配给ViewModel类

var players = new List<PlayersInGame>
            {
                new PlayersInGame
                {
                    PlayerId = 1,
                    GameId = 1,
                    PlayerName = "Manu Ginobili",
                    TeamId = 1,
                    TeamName = "Spurs"
                },
                new PlayersInGame
                {
                    PlayerId = 3,
                    GameId = 1,
                    PlayerName = "Michael Jordan",
                    TeamId = 1,
                    TeamName = "Spurs"
                },
                new PlayersInGame
                {
                    PlayerId = 3,
                    GameId = 2,
                    PlayerName = "Michael Jordan",
                    TeamId = 3,
                    TeamName = "Bulls"
                },
                new PlayersInGame
                {
                    PlayerId = 2,
                    GameId = 1,
                    PlayerName = "James Harden",
                    TeamId = 2,
                    TeamName = "Rockets"
                }
            };

            var games = new List<Games>
            {
                new Games
                {
                    GameId = 1,
                    AwayTeamId = 2,
                    AwayTeamName = "Rockets",
                    AwayTeamScore = 107,
                    HomeTeamId = 1,
                    HomeTeamName = "Spurs",
                    HomeTeamScore = 110
                },
                new Games
                {
                    GameId = 2,
                    AwayTeamId = 2,
                    AwayTeamName = "Rockets",
                    AwayTeamScore = 107,
                    HomeTeamId = 3,
                    HomeTeamName = "Bulls",
                    HomeTeamScore = 110
                }
            };

            /*
           string PlayerName,
           string Teams,
           int GameCount,
           int NumberOfWins*/

            var result = (from g in games
                          join p in players on g.GameId equals p.GameId
                          select new
                          {
                              PlayerNAme = p.PlayerName,
                              Teams = string.Join(",", players.Where(x => x.PlayerName == p.PlayerName).Select( m=> new { m.TeamName })),
                              GameCount = players.Count(x => x.PlayerName == p.PlayerName),
                              NumberOfWins = games.Count(m => ((players.Where(x => x.PlayerName == p.PlayerName).Select(x => x.TeamId)).Contains(m.AwayTeamId) && m.AwayTeamScore > m.HomeTeamScore) || ((players.Where(x => x.PlayerName == p.PlayerName).Select(x => x.TeamId)).Contains(m.HomeTeamId) && m.HomeTeamScore > m.AwayTeamScore))
                          }
                          ).Distinct();

enter image description here