我该如何修改以下代码,以便每次从数据库中获取50个不同的随机数据?
return (from examQ in idb.Exam_Question_Int_Tbl
where examQ.Exam_Tbl_ID==exam_id
select examQ).OrderBy(x=>x.Exam_Tbl_ID).Take(50);
http://msdn.microsoft.com/en-us/library/system.guid.newguid.aspx
return (from examQ in idb.Exam_Question_Int_Tbl
where examQ.Exam_Tbl_ID==exam_id
select examQ).OrderBy(x => Guid.NewGuid()).Take(50);
ORDER BY NEWID()
。正如评论中所述,最好使用类似于Fisher-Yates Shuffle的算法,这里提供了一种实现方法:https://dev59.com/2XRC5IYBdhLWcg3wOOL1#375446
集合有多大?您能将它们全部选择到内存中,然后选择一个随机集合吗?如果可以的话,那么Is using Random and OrderBy a good shuffle algorithm?中的Shuffle算法是一个不错的选择。
return idb.Exam_Question_Int_Tbl
.Where( e => e.Exam_Tbl_ID == exam_id )
.ToList()
.Shuffle()
.Take( 50 );
如果不行的话,我建议使用一个存储过程,根据 newid()
进行排序(SQL Server 随机排序)。我认为在 C# 中基于随机数生成器的表达式无法转换成 LINQ to SQL/Entities。
如果你遇到了和我一样的问题...
int Limit = 24;
return (from Q in Context.table
where Q.some_key == 1234
select new classDataType() {
FirstAttribute = Q.FirstCol,
SecondAttribute = Q.SecondCol,
ThirdAttribute = Q.ThirdCol
}).ToList().OrderBy(x => Guid.NewGuid()).Take(Limit).ToList();
在使用OrderBy-NewGuid-Method之前,由于sql-linq需要它是一个列表,因此您可能需要将其更改为列表。
return (...-SQL-SELECT-LINQ-...)
.ToList() //****
.OrderBy(x => Guid.NewGuid()).Take(Limit).ToList();
x => Guid.NewGuid()
。在时间t+n:A<B是正确的,因为您仍然使用了相同的方法。排序函数不是用来打乱顺序的,这可能会导致最坏情况下出现无限循环。 - L.B.Select( x => new { Guid = Guid.NewGuid, Question = x } ).OrderBy( x => x.Guid ).Select( x => x.Question ).Take(50);
可以用于内存选择,但是你必须排序,最佳算法平均为O(nlogn)。Durstenfeldt算法通过取集合并将每个元素依次与尚未迭代的集合中的随机元素交换来工作。这提供了随机的排序,但只需要O(n)个操作。 - tvanfossonORDER BY NEWID()
将非常慢。如果您考虑它的工作原理,它会为每一行生成一个随机数,然后对它们进行排序。对整个表进行排序是慢的。如果是这种情况,请使用另一种策略,例如:http://msdn.microsoft.com/en-us/library/cc441928.aspx(请记住不要使用TOP
,而是先在结果中使用ORDER BY NEWID()
),或者使用在 SQL Server >=2005 中可用的TABLESAMPLE
子句。该子句使其返回数据的随机页,因此仅触摸了部分数据。非常快速。 - NothingsImpossible.Take(n)
且n>elements.Count
时才能正常工作。 - Bellash