.net Linq:如何按一个表的总和和另一个表的计数排序

.net Linq:如何按一个表的总和和另一个表的计数排序,.net,linq-to-sql,lambda,sql-order-by,.net,Linq To Sql,Lambda,Sql Order By,根据a,我得到了以下LINQ表达式 Events.Where(Function(e) e.EventDate >= Date.Today) _ .OrderByDescending(Function(e) (((e.EventVotes.Sum(Function(s) s.Vote)) * 2) + (e.Comments.Count))) _ .Skip(0) _ .Take(5) 它将转换为以下SQL -- Re

根据a,我得到了以下LINQ表达式

Events.Where(Function(e) e.EventDate >= Date.Today) _
            .OrderByDescending(Function(e) (((e.EventVotes.Sum(Function(s) s.Vote)) * 2) + (e.Comments.Count))) _
            .Skip(0) _
            .Take(5)
它将转换为以下SQL

-- Region Parameters
DECLARE @p0 DateTime2 = '2011-01-17 00:00:00.0000000'
DECLARE @p1 Int = 2
DECLARE @p2 Int = 0
DECLARE @p3 Int = 5
-- EndRegion
SELECT [t3].[ID], [t3].[UserID], [t3].[RegionID], [t3].[LocationID], [t3].[Title], [t3].[Description], [t3].[EventDate], [t3].[URL], [t3].[Phone], [t3].[TicketPriceLow], [t3].[TicketPriceHigh], [t3].[DatePosted], [t3].[isHighlighted]
FROM (
    SELECT ROW_NUMBER() OVER (ORDER BY (((
        SELECT SUM([t1].[Vote])
        FROM [dbo].[EventVotes] AS [t1]
        WHERE [t1].[EventID] = [t0].[ID]
        )) * @p1) + ((
        SELECT COUNT(*)
        FROM [dbo].[Comments] AS [t2]
        WHERE [t2].[EventID] = [t0].[ID]
        )) DESC) AS [ROW_NUMBER], [t0].[ID], [t0].[UserID], [t0].[RegionID], [t0].[LocationID], [t0].[Title], [t0].[Description], [t0].[EventDate], [t0].[URL], [t0].[Phone], [t0].[TicketPriceLow], [t0].[TicketPriceHigh], [t0].[DatePosted], [t0].[isHighlighted]
    FROM [dbo].[Events] AS [t0]
    WHERE [t0].[EventDate] >= @p0
    ) AS [t3]
WHERE [t3].[ROW_NUMBER] BETWEEN @p2 + 1 AND @p2 + @p3
ORDER BY [t3].[ROW_NUMBER]
我现在的问题是,当一些活动没有任何投票或评论时,就开始排序了

下面是EventVotes表的外观(整体)

Comments表是完全空的,因此,由于我们只是对其进行
计数,我们可以假设所有内容都返回空值

现在,当我运行上面的查询时,结果顺序如下

52
51
53
1
2
三,

“应该”是什么时候

52
51
1
2
3
五十三

因为事件编号53的投票计数为“-1”,而事件编号1、2和3的投票计数为“0”

有谁能帮助我们找出如何增强Linq表达式来解释尚未投票的事件吗

这是一个截图

编辑: 好的,我将LinqPad中的查询简化为这个,结果是我只得到三个结果

Events.OrderByDescending(Function(e) (((e.EventVotes.Sum(Function(s) s.Vote)) * 2) + (e.Comments.Count)))
这告诉我的是orderby只获取这三个结果(51、52、53),然后将其余结果附加到order子句之后。我需要找到一种方法,将剩余的“null”结果包含在Lambda表达式中。

这里是一个C#解决方案。我试着把它翻译成VB,但我的VB技能(老实说,还有学习它的愿望)是零,我放弃了。我将努力突出关键点,以帮助翻译

Events.Where(Function(e) e.EventDate >= Date.Today) _
            .OrderByDescending(Function(e) (((e.EventVotes.Sum(Function(s) s.Vote)) * 2) + (e.Comments.Count))) _
            .Skip(0) _
            .Take(5)
以下是完整的声明:

context.Events.OrderByDescending(e => (((e.EventVotes.Sum(s => (int?)s.Vote) ?? 0) * 2) + e.Comments.Count))
关键是首先将
s.Vote
强制转换为可为空的整数,这样
Sum()
的结果将是可为空的整数。可为null的结果允许显式检查null,如果结果确实为null,则在剩余的计算中使用零

出于VB翻译的目的,
??
是一个C#null合并运算符,其中(例如)
myNullableIntVar??0
的计算结果为myNullableIntVar的值,如果为null,则为0

下面是由上述语句FWIW生成的SQL:

exec sp_executesql N'SELECT [t0].[EventID], [t0].[Name]
FROM [dbo].[Events] AS [t0]
ORDER BY ((COALESCE((
    SELECT SUM([t2].[value])
    FROM (
        SELECT [t1].[Vote] AS [value], [t1].[EventID]
        FROM [dbo].[EventVotes] AS [t1]
        ) AS [t2]
    WHERE [t2].[EventID] = [t0].[EventID]
    ),@p0)) * @p1) + ((
    SELECT COUNT(*)
    FROM [dbo].[Comments] AS [t3]
    WHERE [t3].[EventID] = [t0].[EventID]
    )) DESC',N'@p0 int,@p1 int',@p0=0,@p1=2

按字符串进行编辑 我在下面添加了VB.NET版本-这完全符合预期。我试图执行
DirectCast(s.Vote,Integer?
),但它抛出了一个错误,表示
Integer
无法转换为
Integer?
,因此我不得不采用这种方法

Events.OrderByDescending(Function(e) (((If(e.EventVotes.Sum(Function(s) s.Vote),
                                           e.EventVotes.Sum(Function(s) s.Vote),
                                           0)) * 2) + e.Comments.Count))
这导致了这个SQL查询

-- Region Parameters
DECLARE @p0 Int = 0
DECLARE @p1 Int = 2
-- EndRegion
SELECT [t0].[ID], [t0].[UserID], [t0].[RegionID], [t0].[LocationID], [t0].[Title], [t0].[Description], [t0].[EventDate], [t0].[URL], [t0].[Phone], [t0].[TicketPriceLow], [t0].[TicketPriceHigh], [t0].[DatePosted], [t0].[isHighlighted]
FROM [dbo].[Events] AS [t0]
ORDER BY ((
    (CASE 
        WHEN (CONVERT(Bit,(
            SELECT SUM([t1].[Vote])
            FROM [dbo].[EventVotes] AS [t1]
            WHERE [t1].[EventID] = [t0].[ID]
            ))) = 1 THEN (
            SELECT SUM([t2].[Vote])
            FROM [dbo].[EventVotes] AS [t2]
            WHERE [t2].[EventID] = [t0].[ID]
            )
        ELSE @p0
     END)) * @p1) + ((
    SELECT COUNT(*)
    FROM [dbo].[Comments] AS [t3]
    WHERE [t3].[EventID] = [t0].[ID]
    )) DESC

我删除了我的答案,因为我无法提供帮助,也希望人们能看到这个问题的0个答案,并且更有可能阅读它并帮助您解决问题。我最后的怀疑是您的sql语句中的over子句,但我不确定它应该是什么,对不起。谢谢@Brian-我肯定不知道这里是什么。请注意:您最好像我相信Stackoverflow那样,将每个事件的投票总数缓存在事件表本身中。您必须非常小心并发性问题,但这可能是一个巨大的性能胜利。当然,只有评测可以确定,但我相信这个解决方案实际上会更容易。。然后你完全避免了你现在面临的问题。疯狂猜测,但是事件1、2和3的票数是否为空,小于任何有效数字?我不知道为什么它不会默认为零。是的,1,2和3的票数为空。我会试试这个。我确实尝试了内联if语句,但没有首先强制转换为null。谢谢。是的,就是这样。我已经编辑了你的答案以显示VB版本。