Рандомизированный запрос Linq2SQl, который возвращает слишком тяжелый SQL - PullRequest
0 голосов
/ 16 декабря 2009

Я использую следующее для реализации рандомизированных результатов в Linq2SQL:

  partial class OffertaDataContext
    {
        [Function(Name = "NEWID", IsComposable = true)]
        public Guid Random()
        {
            throw new NotImplementedException();
        }
    }

В следующем запросе:

IEnumerable<Enquirys> visibleOnSite =  Enquirys.Where(e => 
    e.EnquiryPublished != null && 
    e.Status != 0 &&
    e.Status != 3 &&
    e.Status != 4 &&
    e.Status != 5
);

var linq = (
            from e in db.EnquiryAreas
            from w in db.WorkTypes
            where
            e.SeoPriority != 0 &&
            e.HumanId != null &&
            w.SeoPriority != 0 &&
            e.HumanId != null &&
            e.SeoPriority * w.SeoPriority > 20 &&
            visibleOnSite.Any(f => f.WhereId == e.Id && f.WhatId == w.Id)
            select new
            {
                HWhereId = e.Id,
                WhereDescription = e.DescriptionText,
                HWhatId = e.Id,
                WhatDescription = e.DescriptionText
            }
        ).OrderBy(e => db.Random()).Take(14);

У меня проблема с результатом SQL:

SELECT [t3].[Id] AS [HWhereId], [t3].[DescriptionText] AS [WhereDescription], [t3].[Id2] AS [HWhatId], [t3].[DescriptionText2] AS [WhatDescription]
FROM (
    SELECT TOP (7) [t0].[Id], [t0].[DescriptionText], [t1].[Id] AS [Id2], [t1].[DescriptionText] AS [DescriptionText2]
    FROM [dbo].[EnquiryAreas] AS [t0], [dbo].[WorkTypes] AS [t1]
    WHERE ([t0].[SeoPriority] <> 0) AND ([t0].[HumanId] IS NOT NULL) AND ([t1].[SeoPriority] <> 0) AND ([t0].[HumanId] IS NOT NULL) AND (([t0].[SeoPriority] * [t1].[SeoPriority]) > 20) AND (EXISTS(
        SELECT NULL AS [EMPTY]
        FROM [dbo].[Enquirys] AS [t2]
        WHERE ([t2].[EnquiryPlace] = ([t0].[Id])) AND ([t2].[EnquiryWorkType] = ([t1].[Id])) AND ([t2].[EnquiryPublished] IS NOT NULL) AND ([t2].[Status] <> 0) AND ([t2].[Status] <> 3) AND ([t2].[Status] <> 4) AND ([t2].[Status] <> 5)
        ))
    ORDER BY NEWID()
    ) AS [t3]
ORDER BY NEWID()

Где все работает нормально, если я удаляю внутренний ORDER BY NEWID (). (С обоими запрос завершается слишком долго). Есть ли способ, которым я могу изменить свой Linq2SQL, чтобы только привести к внешнему ORDER BY NEWID (). Если нет, то какой-нибудь другой обходной путь? Другие способы реализации Random?

1 Ответ

0 голосов
/ 16 декабря 2009

Все зависит от того, насколько случайно вы хотите ваши данные. Если псевдослучайный результат приемлем, то вы можете использовать опцию TABLESAMPLE в SELECT, см. Ограничение результирующих наборов с помощью TABLESAMPLE . Прочтите ссылку в MSDN, так как она объясняет некоторые ограничения, связанные с TABLESAMPEL, особенно при использовании вместе с JOIN.

Если нужна действительно случайная выборка, есть альтернативы ORDER BY NEWID (). Немного лучшим решением является использование NEWID () в предложении WHERE в сочетании со скалярно-зависимым скаляром для принудительного вычисления в каждой строке:

SELECT * FROM ...
WHERE 0.01 >= CAST(CHECKSUM(NEWID(), ID) & 0x7fffffff AS float) 

Эта таблица не сортируется, но все равно выполняется тщательное сканирование. Переверните страницу LINQ, и вы не будете намного лучше, чем ORDER BY.

Если ни одно из решений не является приемлемым, то, возможно, пришло время пересмотреть требования, на этот раз с лучшим пониманием реляционной алгебры 101. После хорошего понимания понятий отношения, кортежа и ключа, здоровое естественное желание отодвинуться назад по идее «случайное отношение» должен решить вашу проблему ...

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...