订购3级物件

时间:2018-07-17 06:20:41

标签: c# sql entity-framework

我有这个计划

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,希望对您有帮助

2 个答案:

答案 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 |

sqlfiddle