Linq: Как заказать по сумме одного стола и по счету другого - PullRequest
3 голосов
/ 18 января 2011

Согласно предыдущему вопросу , у меня есть следующее выражение 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 (полностью)

| UserID | EventID | Vote |    
| 1      | 51      | 1    |   
| 1      | 52      | 1    |   
| 2      | 52      | 1    |   
| 1      | 53      | 1    |   
| 2      | 53      | -1   |   
| 3      | 53      | -1   |

Таблица комментариевполностью пустой, поэтому, поскольку мы просто выполняем Count, мы можем предположить, что все возвращается в нуль.

Теперь, когда я запускаю запрос выше, порядок результатов следующий:

52
51
53
1
2
3

Когда это "должно" быть

52
51
1
2
3
53

, поскольку событие 53 имеет счетчик голосов «-1», а события 1, 2и 3 имеют количество голосов «0»

Может кто-нибудь помочь выяснить, как улучшить выражение Linq для учета событий, за которые не проголосовали?

Вот скриныhot

alt text

EDIT:

Хорошо, поэтому я упростил запрос в LinqPad до этого, и в результате я получил только три результата.

Events.OrderByDescending(Function(e) (((e.EventVotes.Sum(Function(s) s.Vote)) * 2) + (e.Comments.Count)))

Это говорит мне о том, что orderby захватывает только эти три результата (51, 52, 53), а затем добавляет остальные результаты ПОСЛЕ условия заказа.Мне нужно найти способ включить остальные «нулевые» результаты в лямбда-выражение.

1 Ответ

1 голос
/ 19 января 2011

Вот решение на C #. Я пытался перевести это на VB, но мои навыки VB (и желание учиться этому, честно) нулевые, и я сдался. Я постараюсь выделить критические моменты, чтобы помочь с переводом.

Вот полное утверждение:

context.Events.OrderByDescending(e => (((e.EventVotes.Sum(s => (int?)s.Vote) ?? 0) * 2) + e.Comments.Count))

Важно то, что s.Vote сначала приводится к пустому целому числу, так что результатом Sum() будет нулевое целое число. Обнуляемый результат позволяет вам явно проверять наличие нуля и использовать ноль для остальной части вычисления, если результат действительно был нулевым.

Для целей перевода на VB ?? является оператором C # null-coalesce, где (например) myNullableIntVar ?? 0 оценивается как значение myNullableIntVar или, если оно равно null, то 0.

Вот SQL, сгенерированный вышеприведенным оператором, FWIW:

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

Редактировать с помощью rockinthesixstring

Я добавил версию 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
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...