2016-09-14 2 views
1

Ich mag würde eine Datenbank-Tabelle abzufragen, die unten wie das vereinfachten Beispiel aussieht:Linq Abfrage Zeilen auszuwählen, wo eine Spalte ein Maximalwert ist

Quote | Sequence | Item 
-------|-----------|----- 
    1 | 1.0M | a 
    1 | 2.0M | a 
    1 | 3.0M | a 
    1 | 1.0M | b 
    1 | 2.0M | b 
    1 | 3.0M | b 
    2 | 1.0M | x 
    2 | 2.0M | x 
    3 | 1.0M | y 

und ich brauche eine Abfrage, die alle Zeilen für eine bekommt gegeben Quote wo die Sequence der Maximalwert für diese Spalte ist:

Quote | Sequence | Item 
-------|-----------|----- 
    1 | 3.0M | a 
    1 | 3.0M | b 
    2 | 2.0M | x 
    3 | 1.0M | y 

ich verwende F# und System.Data.Linq.

kann ich

let quoteQuery = 
    query{ 
     for row in db.[TABLE] do 
     select row 
     } 

verwenden, um alle Zeilen zu bekommen, aber ich weiß nicht, Linq gut genug - noch - dies zu modifizieren, um die Abfrage zu haben, um die gewünschten Ergebnisse produzieren. Ich habe versucht, the answer from this question in einem Versuch zu verwenden, um meine Abfrage zu ändern, aber ich habe eine Wand in versucht, zu ändern (raten?) Die Syntax/Sprache notwendig.

Es gibt einige SQL-Beispiele, die ich finden kann, aber nur wenige, die Linq-spezifisch sind.

+0

Laut [der Dokumentation] (https://docs.microsoft.com/de-de/dotnet/articles/fsharp/sprachreferenz/query-expressions) sollten Sie in der Lage sein, 'maxBy' zu verwenden ... –

+3

BTW, F # Abfrageausdrücke sind nicht * LINQ *; Sie sind * F # Abfrageausdrücke *. –

Antwort

1

Wie in Kommentaren angedeutet, ist dies nicht Linq, sondern f # Abfrageausdrücke.

Und das ist eigentlich nicht wirklich, worum es sich bei dieser Frage handelt.

Seine mehr und relationalen Algebra. Oder etwas ...

Das sagte: Die Sache hier ist, dass, wenn Sie gruppieren und dann das maximale Element jeder Gruppe bekommen, dann sind Sie gut zu gut. Beachten Sie, dass der Beispielcode nicht gegen eine DB oder auf andere Weise funktioniert, aber das sollte ziemlich leicht ersetzbar sein.

type Table = 
    { 
     Quote:int 
     Sequence: decimal 
     Item: string 
    } 

let createTableEntry (q,s,i) = 
    { 
     Quote = q 
     Sequence = s 
     Item = i 
    } 

let printTR {Quote=q;Sequence=s;Item=i} = printfn "%A | %A | %A" q s i 

let table = 
    [ 
     (1 , 1.0M , "a") 
     (1 , 2.0M , "a") 
     (1 , 3.0M , "a") 
     (1 , 1.0M , "b") 
     (1 , 2.0M , "b") 
     (1 , 3.0M , "b") 
     (2 , 1.0M , "x") 
     (2 , 2.0M , "x") 
     (3 , 1.0M , "y") 
    ] 
    |> List.map createTableEntry 

let result = 
    table 
    |> List.groupBy (fun x -> x.Quote, x.Item) //group "unique" by Quote&Item 
    |> List.map (fun x -> snd x |> List.max) //get max of each group, i.e. max of Sequence 


result |> Seq.iter printTR 

1 | 3.0M | "a" 
1 | 3.0M | "b" 
2 | 2.0M | "x" 
3 | 1.0M | "y" 

Nachtrag

nach Ivan Stoev hatte teilweise "falsch" beantwortet. Hier ist eine „korrigierte“ Version, die funktioniert die „gleiche“ (nicht wirklich gleich, aber ...) wie oben:

let quoteQuery = 
    query { 
     for row in table do 
     groupBy (row.Quote, row.Item) into g 
     let maxRow = 
      query { 
       for row in g do 
       sortBy row.Sequence 
       headOrDefault 
      } 
     select maxRow 
    } 

quoteQuery |> Seq.iter printTR 

Nachtrag II

Da ich bearbeitet und sagte, dass Ivans Antwort war nicht wirklich das gleiche wie das erste Codebeispiel, habe ich auch hinzugefügt ein, dass „genau das gleiche“ mit Abfrage-Ausdrücken ist: sind

let quoteQuery' = 
    query { 
     for row in table do 
     groupBy (row.Quote, row.Item) into g 
     let maxRow = 
      query { 
       for row in g do 
       maxBy row.Sequence 
      } 
     select (fst g.Key, maxRow, snd g.Key) 
    }|>Seq.map createTableEntry 

quoteQuery' |> Seq.iter printTR 
0

F # Abfrage Ausdruck Abfrageausdruck genannt, weil sie (losely) LINQ-Abfragesyntax folgen (vs Methoden-Syntax) und sie implementieren Linq.IQueriable. Also denke ich auch über sie als LINQ nach. Obwohl es nicht idiomatisch ist, kann die obige Abfrage in Methodensyntax neu geschrieben werden. Wenn Sie MoreLinq nuget, ist es ziemlich succint. "Diebstahl" die obige Tabelle Definition von @HelgeReneUrholm:

open MoreLinq 

table 
    .GroupBy(fun x -> (x.Quote,x.Item)) 
    .Select(fun x -> x.MaxBy(fun x -> x.Sequence)) |> Seq.iter printTR 

1 | 3.0M | "a"
1 | 3.0M | "b"
2 | 2.0M | "x"
3 | 1.0M | "y"

Verwandte Themen