我有这个计划
Document
DocumentId
Position
PositionId
DocumentId
Coordonate
CoordonateId
PositionId
Km
Road
RoadId
CoordonateId
Name
我需要按Road.Name排序,然后按最低Coordonate.Km排序。我试图在SQL和EF中对它们进行排序,但是没有运气,所以现在我使用的代码很慢:
foreach (var document in documents)
foreach (var position in documentPositions)
{
if (!position.Coordonates.Any())
continue;
var minKm =
position.Coordonates.OrderBy(a => a.Km).FirstOrDefault().Km.Value;
dictionary.Add(document, minKm);
break;
}
var sorted= dictionary.OrderBy(a => a.Key.RoadName).ThenBy(a => a.Value);
document.RoadName是一个属性,用于连接文档中可能存在的所有Road.Name。
LE: 我在http://sqlfiddle.com/#!18/90b00/2/0做了一个sqlfiddle,希望对您有帮助
答案 0 :(得分:1)
您无需先使用OrderBy
即可找到最小值,然后使用FirstOrDefault
来查找最小值,而应该使用Min
,它应该快一点。
var minKm = position.Coordinates.Min(coord => coord.Km.Value);
更新:也许您的代码很慢,因为position.Coordinates没有从数据库加载,并且您的代码对每个文档都进行了额外的数据库往返,这就是为什么它很慢。请确保已加载所有数据,并且foreach循环实际上导致了这种缓慢。如果不包括坐标数据,则可以在您的EF查询中添加Include(...)
语句。
答案 1 :(得分:1)
您可以使用Coordonates
表编写子查询,将rank
函数与Windows函数结合使用以获取samllest
公里,然后执行join
select Documents.DocumentId,
Documents.Name,
Roads.Name,
MIN(km) km
from Documents
INNER JOIN Positions ON Documents.DocumentId=Positions.DocumentId
INNER JOIN (
select
PositionId,
CoordonateId,
km,
rank() over(partition by PositionId order by Km) rn
from Coordonates
) Coordonates ON Positions.PositionId=Coordonates.PositionId and rn =1
INNER JOIN Roads ON Coordonates.CoordonateId=Roads.CoordonateId
group by Documents.DocumentId,
Documents.Name,
Roads.Name
Order By Roads.Name,km
[结果] :
| DocumentId | Name | Name | km |
|------------|------|------|----|
| 2 | Doc2 | A1 | 10 |
| 1 | Doc1 | A2 | 10 |
| 3 | Doc3 | A2 | 15 |