简体   繁体   中英

Order a 3 level object

I have this scheme

Document
    DocumentId

Position
    PositionId
    DocumentId

Coordonate
    CoordonateId
    PositionId
    Km

Road
    RoadId
    CoordonateId
    Name

I need to order the documents by Road.Name and then by lowest Coordonate.Km. I tried to order them in SQL and EF but with no luck so now I use this code that is very slow:

    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 is a property that concatenates all the Road.Names that may be in the document.

LE: I made a sqlfiddle at http://sqlfiddle.com/#!18/90b00/2/0 Hope that helps

You can find min value without using OrderBy and then FirstOrDefault Instead use Min which should be a little bit faster.

var minKm = position.Coordinates.Min(coord => coord.Km.Value);

Update: maybe your code is slow because position.Coordinates is not loaded from the database and your code does extra database roundtrip for every document which is why it is slow. Please ensure all data is already loaded and the foreach loop is actually causing that slowness. If coordinates data aren't included you can add Include(...) statement into your EF query.

You can write a subquery by Coordonates table, using rank function with windows function to get the samllest km, then do 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

[Results] :

| DocumentId | Name | Name | km |
|------------|------|------|----|
|          2 | Doc2 |   A1 | 10 |
|          1 | Doc1 |   A2 | 10 |
|          3 | Doc3 |   A2 | 15 |

sqlfiddle

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM