Skocz do zawartości

Inner Join za pomocą LINQ

Polecane posty

Witam,

Chciałbym za za pomocą Raportu własnego LINQ zrealizować odpowiednik SQLowego Inner Join.

Przykładowo chciałbym dla każdej FS zsumować wszystkie pozycje z usługami i przemnożyć je przez wartość pola własnego FS w danym okresie czasu.

Potrafię wyciągnąć dokumenty określonego typu w danym okresie:

    .Where (dok =>(dok.Symbol == "FS")
                &&
                (dok.DataWydaniaWystawienia >= DataOd &&
                 dok.DataWydaniaWystawienia <= DataDo
                )
      )
    .Select((DokumentHandlowy dokumentHandlowy) => new Wynik
    {
        Id = dokumentHandlowy.Id,
        SymbolDok = dokumentHandlowy.NumerWewnetrzny.PelnaSygnatura,
        polewlasne = (dokumentHandlowy as DokumentDS).PolaWlasneAdv.polewlasne,
    });

Potrafię odfiltrować usługi i wykonać operacje z polem własnym:

    .Where (poz => poz.RodzajAsortymentuId==1
    )
    .Select((PozycjaDokumentu pozycjaDokumentu) => new Wynik
    {
        Id = pozycjaDokumentu.Id,
        Nazwa = pozycjaDokumentu.AsortymentAktualny.Nazwa,
        ilosc = pozycjaDokumentu.Ilosc,
        dokNazwa = pozycjaDokumentu.Dokument.NumerWewnetrzny.PelnaSygnatura,

        prowizja = pozycjaDokumentu.Ilosc * pozycjaDokumentu.Wartosc.NettoPoRabacie * (pozycjaDokumentu.Dokument as DokumentDS).PolaWlasneAdv.polewlasne / 100,
    });

Ale ni jak nie umiem tego połączyć w coś na kształt inner join.

Proszę o jakąś wskazówkę.

Pozdrawiam

Korin Bobowski

CorNET - Korin Bobowski

Edytowane przez Korin Bobowski
Link to postu

Należy wykonać odpowiednie zapytanie/operację na kolekcji pozycji dokumentu:

.Where (dok =>(dok.Symbol == "FS")
                &&
                (dok.DataWydaniaWystawienia >= DataOd &&
                 dok.DataWydaniaWystawienia <= DataDo
                )
      )
    .Select(dok => new {
        Dokument = dok,
        PozycjeUslug = dok.Pozycje.Where(poz => poz.RodzajAsortymentuId==1)
    })
    .Select(tmp => new Wynik
    {
        Id = tmp.Dokument.Id,
        SymbolDok = tmp.Dokument.NumerWewnetrzny.PelnaSygnatura,

        sumarycznailoscuslug = tmp.PozycjeUslug.Any() 
            ? tmp.PozycjeUslug.Sum(p => p.Ilosc)
            : 0m,
        sumarycznaprowizjaoduslug = tmp.PozycjeUslug.Any() 
            ? tmp.PozycjeUslug
                .Sum(pozycjaDokumentu => pozycjaDokumentu.Ilosc * pozycjaDokumentu.Wartosc.NettoPoRabacie * (pozycjaDokumentu.Dokument as DokumentDS).PolaWlasneAdv.polewlasne / 100)
            : 0m,
    });

Dodałem jeden poziom selecta z typem anonimowym, aby mieć raz przefiltrowaną kolekcję pozycji, bo potem korzystam z niej 4 razy.

Link to postu

Rewelacja wszystko działa idealnie dodałem jeszcze warunek aby pomijał dokumenty bez usług ale i tak nie ogarniam tematu.

    .Where (dok =>(dok.Symbol == "FS") &&
                  (dok.WartoscUslugNetto > 0) &&
                  (dok.DataWydaniaWystawienia >= DataOd &&
                   dok.DataWydaniaWystawienia <= DataDo)
      )

A czy istnieje jakaś możliwość dodania wiersza podsumowującego całe zestawienie czyli ile było usług wykonanych i jaka była suma prowizji?

Edytowane przez Korin Bobowski
Link to postu

No to jest rozwiązanie oczywiste bardziej myślałem o magicznej składni języka Linq;)

Ale i tak dziękuję za pomoc.

Nurtuje mnie jeszcze pytanie co oznacza w składni operatora warunkowego czyli "?" wyrażenie 

: 0m

  rozumiem, że jak nie zadziała warunek to ma się to zrobić to, ale co właściwie? ok wpisać "0" ale co to  "m" oznacza?

Pozdrawiam.

Edytowane przez Korin Bobowski
Link to postu

Żeby dodać wiersz podsumowujący należy zrobić Union z podobnym zapytaniem, tylko zsumowanym. To jednak nie ma sensu, bo zapytanie znacznie się komplikuje oraz dwa razy analizuje te same dane co wydłuża czas jego działania, podczas gdy lista podsumowuje pobraną już zawartość.

Ale dla porządku napiszę, że musiałoby to wyglądać tak:

.Where (dok =>(dok.Symbol == "FS" &&
                (dok.WartoscUslugNetto > 0) &&
                (dok.DataWydaniaWystawienia >= DataOd &&
                 dok.DataWydaniaWystawienia <= DataDo)
      ))
    .Select(dok => new {
        Dokument = dok,
        PozycjeUslug = dok.Pozycje.Where(poz => poz.RodzajAsortymentuId==1)
    })
    .Select(tmp => new Wynik
    {
        Id = tmp.Dokument.Id,
        SymbolDok = tmp.Dokument.NumerWewnetrzny.PelnaSygnatura,

        sumarycznailoscuslug = tmp.PozycjeUslug.Any() 
            ? tmp.PozycjeUslug.Sum(p => p.Ilosc)
            : 0m,
        sumarycznaprowizjaoduslug = tmp.PozycjeUslug.Any() 
            ? tmp.PozycjeUslug
                .Sum(pozycjaDokumentu => pozycjaDokumentu.Ilosc * pozycjaDokumentu.Wartosc.NettoPoRabacie * (pozycjaDokumentu.Dokument as DokumentDS).PolaWlasneAdv.polewlasne / 100)
            : 0m,
    })
.ToList()
.Union(
    new object[] { null } 
    .Select(dokument => new {
        PozycjeUslug = source
            .Where(dok =>(dok.Symbol == "FS"  &&
                (dok.WartoscUslugNetto > 0) &&
                (dok.DataWydaniaWystawienia >= DataOd &&
                 dok.DataWydaniaWystawienia <= DataDo)
))
            .SelectMany(dok => dok.Pozycje.Where(poz => poz.RodzajAsortymentuId==1)),
    })
    .Select(tmp => new Wynik
    {
        Id = 0,
        SymbolDok = "Podsumowanie:",
        sumarycznailoscuslug = tmp.PozycjeUslug.Any() 
            ? tmp.PozycjeUslug.Sum(p => p.Ilosc)
            : 0m,
        sumarycznaprowizjaoduslug = tmp.PozycjeUslug.Any() 
            ? tmp.PozycjeUslug
                .Sum(pozycjaDokumentu => pozycjaDokumentu.Ilosc * pozycjaDokumentu.Wartosc.NettoPoRabacie * (pozycjaDokumentu.Dokument as DokumentDS).PolaWlasneAdv.polewlasne / 100)
            : 0m,
    })
).AsQueryable()

 

Język zapytań w raportach własnych LINQ to C#:

?: Operator

decimal (Literals)

 

 

Edytowane przez Jarek K.
Link to postu
×
×
  • Dodaj nową pozycję...