【问题标题】:Query help for voting app in Linq using SQL Server使用 SQL Server 在 Linq 中查询投票应用程序的帮助
【发布时间】:2012-08-21 13:23:45
【问题描述】:

我正在尝试创建查询以获取投票结果。

有一张表格记录了某人所做的每一次投票。人们可以多次投票,但只应考虑最后一次投票。

除了“只应考虑用户的最后一票”部分之外,我已经知道它可以工作了。

这是我的桌子:

表投票:

  id            bigint      PK
  TimeStamp     datetime
  QuestionId    int
  UserId        int

和 Linq 查询:

var total = (float)(_db.Votes).Count(vote => vote.Timestamp>=startWeekDay && vote.Timestamp<endWeekDay);

var results = (from vote in _db.Votes 
                  where vote.Timestamp >= startWeekDay && vote.Timestamp < endWeekDay
                  group vote by new { vote.QuestionId} into g
                  orderby g.Count() descending
                  select new VoteResults()
                      {
                          QuestionID = g.Key.QuestionId, 
                          Percentage = (g.Count() / total * 100.0f),
                      }).ToList();

我的问题:如何更改此查询,以便只考虑每个用户的最后一次投票?

编辑: 鉴于此输入:

{
    UserId = 1,
    QuestionId = 2,
    TimeStamp = Yesterday
},
{
    UserId = 1,
    QuestionId = 1,
    TimeStamp = Today
},
{
    UserId = 2,
    QuestionId = 2,
    TimeStamp = Yesterday
},
{
    UserId = 3,
    QuestionId = 1,
    TimeStamp = Yesterday
}

输出应如下所示:

{
    QuestionID = 2,
    Percentage = 33.3333
},
{
    QuestionID = 1,
    Percentage = 66.66666
}

【问题讨论】:

  • 下载免费的LinqPad 并自己尝试查询,无需编译任何东西......如果你愿意,它甚至可以使用你自己的EntityFramework。
  • 我知道 LinqPad。谢谢。只是我被困在如何扩展查询以添加这个额外的要求。我不明白 linqpad 在这里可以如何帮助我。
  • 为什么 QuestionID = 2 和 Percentage = 33.333?在这种情况下,g.Count() 和 Total 应该是什么?
  • g.count 和 total 我用来计算百分比的方法。在上面的例子中:33% 的用户投了问题 2,66% 的用户投了问题 1。
  • 如果您使用我的旧查询。 questionId 2 的 g.count 为 2,总数为 4。事实上,如果您只考虑每个用户的最后一次投票,它应该是:g.count for questionId 2 为 1(因为投票被新的投票否决),总数应该是 3(因为实际上只有 3 票有效)

标签: c# .net sql-server linq


【解决方案1】:

下面我向您展示我在控制台应用程序中运行的一个测试用例......它应该可以解决您的问题。我用您在示例中传递的数据进行了测试:

public class User
{
    public int UserId {get; set;}
}

public class Question
{
    public int QuestionId { get; set; }
}

public class Vote
{
    public int VoteId {get; set;}
    public DateTime TimeStamp {get; set;}
    public Question Question {get; set;}
    public User User { get; set; }
}

public class VoteResult
{
    public int QuestionId { get; set; }
    public float Percentage { get; set; }
}

public class Program
{
    static void Main(string[] args)
    {
        var question1 = new Question();
        question1.QuestionId = 1;

        var question2 = new Question();
        question2.QuestionId = 2;

        var user1 = new User();
        user1.UserId = 1;

        var user2 = new User();
        user2.UserId = 2;

        var user3 = new User();
        user3.UserId = 3;

        List<Vote> votes = new List<Vote>()
        {
            new Vote()
            { 
                Question = question2,
                TimeStamp = DateTime.Today.AddDays(-1), // Yesterday
                User = user1,
                VoteId = 1
            },

            new Vote()
            { 
                Question = question1,
                TimeStamp = DateTime.Today,
                User = user1,
                VoteId = 2
            },

            new Vote()
            {
                Question = question2,
                TimeStamp = DateTime.Today.AddDays(-1), // Yesterday
                User = user2,
                VoteId = 3
            },

            new Vote()
            {
                Question = question1,
                TimeStamp = DateTime.Today.AddDays(-1), // Yesterday
                User = user3,
                VoteId = 4
            }
        };

        // Group Votes by User and then Select only the most recent Vote of
        // each User
        var results = from vote in votes
                        where vote.TimeStamp >= DateTime.Today.AddDays(-7) &&
                              vote.TimeStamp < DateTime.Today.AddDays(1)
                        group vote by vote.User into g
                        select g.OrderByDescending(v => v.TimeStamp).First();

        // Total Users who voted
        var total = results.Count();

                               // Group Users' votes by Question
        foreach (var result in results.GroupBy(v => v.Question.QuestionId))
        {
            var voteResult = new VoteResult()
            {
                QuestionId = result.Key,
                Percentage = ((float)result.Count() / total) * 100.0f
            };

            Console.WriteLine(voteResult.QuestionId);

            Console.WriteLine(voteResult.Percentage);
        }

    }
}

【讨论】:

  • 嗨 +Leniel Macaferi。如果我正确阅读了您的查询,它会对每个 QuestionID 的所有选票进行排序,而不是最后一个。但是,它应该考虑所有用户的所有投票,但对于任何给定用户,只有最后一个投票。
  • 请稍等...我正在尝试控制台应用程序并将结果发布在这里。 :)
  • +Leniel Macaferi 感谢您的帮助。我已经编辑了我的问题以显示示例输入和输出。
  • 你明白解决方案背后的想法了吗?
  • +leniel macaferi 我仍然敬畏和吸收它。我是否理解正确,首先您过滤整个集合,以便您只有每个用户的唯一投票,然后使用第二个 groupby,您使用之前的结果来获得每个问题的投票?
猜你喜欢
  • 1970-01-01
  • 2016-08-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多