37

F #3.0을 시험해보고 여러 열로 그룹화 할 때 약간의 벽을 치십시오. 시도 할 분명한 것은

query {
    for d in context.table do
    groupBy (d.col1,d.col2) into g
    select (g.Key)
}

하지만 "매개 변수없는 생성자 및 초기화 자만 LINQ to Entities에서 지원됩니다." 예외.

나는 msdn에 대한 예를 찾을 수 없다.

http://msdn.microsoft.com/en-us/library/hh225374(v=vs.110).aspx

http://msdn.microsoft.com/en-us/library/hh361035(v=vs.110).aspx

내 질문이 "F #의 엔터티 프레임 워크 및 익명 형식"하지만 powerpack / F #2.x에 초점을 맞춘 것으로 보이고 F #3.0에 우아한 답변이 있기를 바랍니다 ... 어떤 아이디어?

최신 정보:

브라이언의 게시물을 읽음으로써 CLIMutable 속성을 발견했습니다 :

http://blogs.msdn.com/b/fsharpteam/archive/2012/07/19/more-about-fsharp-3.0-language-features.aspx

나는 꽤 낙천적이어서 시도했다.

[<CLIMutable>]
type MyRecord = { Column1 : int; Column2 : int }

query {
    for d in context.table do
    groupBy {Column1 = col1; Column2 = col2} into g
    select (g.Key)
}

불행히도 나는 똑같은 예외를 얻는다.


  • 튜플에 그룹화하거나 사용자가선택하나? 에러는 "출력"메시지를 참조하는 것으로 보인다. 유형. 어쩌면 선택할지 모른다.g.Count()대신에 무슨 일이 일어나는 지보십시오. 나는 3.0을 시도하지 않았다. 단지 추측한다. - Daniel
  • 나는 상수 "select (1)"을 선택하려고 시도했다. 그리고 같은 것을 얻었다. - Jizugu
  • @ildjarn :g.Key파라미터가없는 생성자가없는 튜플입니다.select 1내 추측이 맞다면 제대로 작동 할 것입니다. - Daniel
  • @ 대니얼 :select g.Key하지 않습니다구성 또는 초기화그러나 새로운 튜플. AFAICT,select (g.Key)~ 될 것입니다.Tuple<Tuple<col1_t, col2_t>>,의 생성자를 호출하는Tuple<'T1>;select g.Key~ 될 것입니다.Tuple<col1_t, col2_t>새 값을 초기화하는 대신 기존 값을 재사용합니다. 물론 예외가 발생했다는 가정하에 실행하고 있습니다.select오히려groupBy, 이것은 완전히 부정확 할 수 있습니다. :-피 - ildjarn
  • 괄호는 그룹화하기위한 것입니다. 이것을 튜플 (tuple)로 만드는 것은 쉼표입니다. 단 하나의 원소를 가진 튜플은 (1,) - Markus Jarderot

7 답변


3

다음은 C #에서 그룹화에 사용되는 여러 열의 예이며 f #으로 변환되었습니다 (지나치게 편집증적인 관리로 인해 모든 이름이 변경되었지만 일관성이 유지되었습니다).

(TheDatabase는 SqlMetal에 의해 생성되었으며 GetSummedValuesResult는 F #레코드 유형 임)

기음#

public static class Reports
{
    public static IReadOnlyList<GetSummedValuesResult> GetSummedValues(TheDatabase db, DateTime startDate, DateTime? endDate)
    {
        var query =
            from sv in db.SomeValues

            where (sv.ADate >= startDate && sv.ADate <= (endDate ?? startDate))

            group sv by new { sv.ADate, sv.Owner.Name } into grouping

            select new GetSummedValuesResult(
                grouping.Key.ADate,
                grouping.Key.Name,
                grouping.Sum(g => g.Value)
            );

        return query.ToList();
    }
}

에프#

type Reports() =
    static member GetSummedValues (db:TheDatabase) startDate (endDate:Nullable<DateTime>) =
        let endDate = if endDate.HasValue then endDate.Value else startDate

        let q = query {
            for sv in db.SomeValues do
            where (sv.ADate >= startDate && sv.ADate <= endDate)

            let key = AnonymousObject<_,_>(sv.ADate, sv.Owner.Name)
            groupValBy sv key into grouping

            select {
                ADate        = grouping.Key.Item1;
                AName        = grouping.Key.Item2;
                SummedValues = grouping.Sum (fun (g:TheDatabaseSchema.SomeValues) -> g.Value)
            }
        }

        List(q) :> IReadOnlyList<GetSummedValuesResult>

그래서 사용할 것이 있습니다.Microsoft.FSharp.Linq.RuntimeHelpers.AnonymousObject

집계 함수를 위해 Seq 모듈을 사용해서는 안된다 !!

SummedValues  = grouping |> Seq.sumBy (fun g -> g.SomeValues)

이 작업을 수행 할지라도 적절한 SQL을 공식화하는 것이 아니라 클라이언트 측에서 집계를 수행합니다.


1

나는 당신의 연결의 첫번째에서 이것을 본다, 나는 그것이 당신이 원하는 것이라고 생각한다.

query {
    for student in db.Student do
    groupValBy student.Name student.Age into g
    select (g, g.Key, g.Count())
}


  • groupValBy는 "지금까지 선택된 각 요소에 대한 값을 선택하고 주어진 키에 의해 요소들을 그룹화한다"라고 기술된다. 핵심은이 경우 여전히 student.Name에 기반한 것입니다. - Jizugu
  • 그래서, 왜 그 학생이 있을까요 .Age? FSharp에서 여러 열을 기준으로 그룹화하는 쉬운 방법이 없다고 생각할 수 없습니다. 비슷한 케이스 - 조인에 대해 - 복합 키를 작성하는 방법? - tomasK
  • 사실이 그룹은student.Age. 첫 번째 인수groupValBy는 저장 될 값이고 두 번째 값은 그룹화 할 키입니다. 단어를 상상해 보라.by첫번째 args와 두번째 args 사이. - latkin

0

groupBy를 사용할 때 집계 함수 (예 : 개수, 합계, 평균 ...)를 선택해야합니다.


  • 이 예제는 실제로 삽화에 불과하며 select (g.Key)는 유용하지는 않지만 작동해야합니다 ... "select (g.Count ()) " 같은 오류가 발생합니다. - Jizugu

0

먼저 쿼리가 실제 데이터로 변환된다는 것을 기억해야합니다.SQL어떤 시점에서. linq은 여러 개의 그룹 키를 하나의 키로 사용하는 것을 지원하지 않는다.Tuple<>. 따라서Tuple<>데이터베이스 호출이 완료된 후에 수행되어야합니다.

둘째, 달성 할 수 있어야합니다.다중 키 그룹화각 키에서 서로 뒤에 여러 그룹을 수행하여

query {
    for d1 in context.table do
    groupBy d1.col1 into g1
    for d2 in g1 do
    groupBy d2.col2 into g2
    select g2
}

F #이 제 모국어가 아니기 때문에 문법이 100 %가 아니라면 저에게 자비를 베풀어주십시오. :) 그러나 개념은 잘 작동합니다.


  • 흥미롭게도 "LINQ to Entities에서 매개 변수없는 생성자 및 초기화 도구 만 지원됩니다." - Jizugu

0

open Microsoft.FSharp.Linq.RuntimeHelpers
open System.Linq

query {
    for d in context.table do
    let t = MutableTuple<_,_>(Item1=d.col1,Item2=d.col2)
    groupValBy d t into g
    select (g.Key,g.Count())
    } 


  • 일하는 것 같습니다. 그러나 select (g.Key) 이상의 항목을 얻는 데 문제가 있습니다. select (g.Count ())를 사용하면 오류가 발생하며 다른 열에서 집계를 수행하는 방법을 알 수 없습니다. 그래도 아이디어를 가지고 노는 - Jizugu

0

//in F#3.0
open Microsoft.FSharp.Linq.RuntimeHelpers
open Microsoft.FSharp.Linq.RuntimeHelpers.LeafExpressionConverter
open System.Linq

//[<CLIMutable>]
//type MyRecord = { Column1 : int; Column2 : int }
// require constructor in F#
// groupBy is not valid

type T(column1 : int, column2 : int)
    member val Colum1=colum1 with get,set
    membre val Colum2=colum2 with get,set

query {
    for d in context.table do
    groupValBy d (NewAnonymousObjectHelper(T(d.Colum1,d.Colume2))) into g
    select (g.Key)
    }


-1

query {  
    for d in context.table do  
    groupBy (new {d.col1, d.col2}) into g  
    select (g.Key) 
}


  • 질문자가 이해할 수 있도록 의견을 추가하십시오. 그렇지 않으면 "마법"입니다. - Eric Fossum
  • new {d.col1, d.col2}C #익명 형식을 생성합니다. 이것은 유효한 F #이 아닙니다. - Jay

연결된 질문


관련된 질문

최근 질문