随机Linq2SQl查询返回太重的SQL

时间:2009-12-16 14:20:10

标签: c# sql-server linq-to-sql tsql

我使用以下命令在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 :(得分:0)

这完全取决于您想要数据的随机性。如果伪随机结果可以接受,那么您可以使用SELECT的TABLESAMPLE选项,请参阅Limiting Result Sets by Using TABLESAMPLE。请阅读MSDN中的链接,因为它解释了TABLESAMPEL的一些限制,特别是在与JOIN结合使用时。

如果需要真正的随机样本,则可以选择ORDER BY NEWID()。稍微好一点的解决方案是在WHERE子句中使用NEWID(),并结合行依赖标量来强制每行进行评估:

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

这不会对表格进行排序,但它仍会进行大量的扫描。抛出LINQ分页,你就不会比ORDER BY好多了。

如果两种解决方案都不可接受,那么也许是时候重新审视这些要求,这一次是对关系代数101的更好理解。在对关系,元组和关键的概念有了很好的把握之后,一种健康的自然冲动可以推迟关于'随机关系'的想法应该可以解决你的问题......