Eloquent poprawne zwrócenie danych

0

mam takie dwie encje

    public function up()
    {
        Schema::create('configurations', function (Blueprint $table) {
            $table->increments('id');
            $table->date('date_from');
            $table->integer('race_id');
            $table->timestamps();
        });
    }

w modelu mam

    public function parameters()
    {
        return $this->hasMany('App\Models\Parameter');
    }

oraz listę parametrów przypisanych do danej konfiguracji

    public function up()
    {
        Schema::create('parameters', function (Blueprint $table) {
            $table->increments('id');
            $table->integer('configuration_id');
            $table->tinyInteger('day');
            $table->decimal('water', 8, 3);
            $table->smallInteger('feed');
            $table->smallInteger('weight');
            $table->decimal('downs');
            $table->timestamps();
     

pytania z założeniami:

  1. Potrzebuję wyciągnąć zsumowaną pod względem ( water, feed, weight, downs ) listę parametrów należące do configuracji o id in (tutaj różnie może być od jednego id po kilka)
$configuration = Configuration::whereIn('race_id', [1, 2])->get();
  1. Z konwencji, jak kodować
return $this->hasMany('App\Models\Parameter'); 
//czy 
return $this->hasMany(Parameter::class');

0

czyli chciałbym osiągnąć mniej więcej wynik takiego zapytania

select p.[day], sum(p.water), sum(p.feed), sum(p.weight), sum(p.downs)
from dbo.parameters p left join dbo.configurations c on c.id = p.configuration_id
where c.race_id in (1,2)
group by p.[day];

nawet jeszcze musiałbym dodać żeby brać TYLKO najnowszą pod względem daty konfigurację dla danego race_id ( bo może ich być kilka a tylko ta z najnowszą datą będzie aktualna )

0
  1. Odwróć to, po co robić to na relacji skoro możesz bezpośrednio na Parameter i tam zrobić whereIn('configuration_id', ....)
  2. stosuje się drugi sposón
0

ad 1
w jakim sensie odwróć.
Zapytanie, które na szybko daje złudzenie poprawnego jest takie ten inner join po to aby wyłuskać najświeższą konfigurację dla danego race_id

select c.id, c.race_id, c.date_from, p.[day], sum(p.water), sum(p.feed), sum(p.weight), sum(p.downs)
from dbo.parameters p left join dbo.configurations c on c.id = p.configuration_id
inner join (
    select race_id, max(date_from) as MaxDate
    from dbo.configurations
    group by race_id
) tm on c.race_id = tm.race_id and c.date_from = tm.MaxDate
where c.race_id in (1,2) 
group by c.id, p.[day], c.race_id, c.date_from
order by 4;

teraz czy coś takiego lepiej wpakować po prostu w jakieś plain query ( zapewne w Laravel można ), czy query builder ( tutaj jeszcze nie wiem jak ten inner zakodowąć )

0

Nie patrz na to co generuje tylko na to czy wynik jest poprawny, to jest orm, nie masz nad nim wpływu jak to robi. To co ty zrobisz jednym długim zapytaniem orm zrobi kilkoma mniejszymi. Czy wydajność spadnie? Zależy od przypadku. Nie pisz nic korzystając z czystych zapytań, jeśli już tak bardzo chcesz to użyj query buildera.

0
mr_jaro napisał(a):

To co ty zrobisz jednym długim zapytaniem orm zrobi kilkoma mniejszymi.

To jeszcze zależy jaki ORM.... są takie gdzie da się zrobić skomplikowane JOINy bez dzielenia na wiele zapytań.

0

@TomRZ: tak, ale mówię o tym konkretnym o którym toczy się dyskusja, więc nie wiem co mają inne skoro autor pyta się o eloquenta. W eloquencie tez można wymusić jointy tylko po co? Rzadko kiedy zdarza się by coś oparte o php używało baz innych niż mysql lub jego forki, a złożone zapytania to jednak domena np postgresa, a nie mysql.

0

@mr_jaro: to zapytanie sql bylo tylko do zobrazowania jaki wynik jest porzadany.
Nie chcialbym w tym przypadku uzywac ani query buildera albo plain sql.

0

Chciałbym wrócić do tematu. Chciałbym użyć query buildera w ostateczności. Jak ogarnąć to przez ORM?

0

Poczytaj o zmiennej $appends na modelu, i jak generować dynamiczne atrybuty. Stwórz w taki sposób 4 atrybuty (same gettery) z sumami i one automatycznie dodadzą Ci się przy pobieraniu modelu.

Wszystko inne raczej standardowo wyciągasz.

0

@mefsh: możesz rzucić jakimś kodem? nie do końca rozumiem jak zapisać sumy na modalach, oraz jak wyciągnać najnowsze konfiguracje dla danego race_id.

0

na ten moment zrobiłem coś takiego

public function cardPrintout(int $documentId)
    {
        $races = [];
        $document = $this->documentRepository->get($documentId);

        foreach($document->details as $d)
        {
            array_push($races, $d->id);
        }

        $sql = "select  p.[day] as day, sum(p.water) as water, sum(p.feed) as feed, sum(p.weight) as weight, sum(p.downs) as downs
                    from dbo.parameters p left join dbo.configurations c on c.id = p.configuration_id
                    inner join (
                        select race_id, max(date_from) as MaxDate
                        from dbo.configurations
                        group by race_id
                    ) tm on c.race_id = tm.race_id and c.date_from = tm.MaxDate
                    where c.race_id in (1,2,3)  // problem jak zbindować te wartości
                    group by p.[day]
                    order by 4";

        $configuration = DB::select( $sql );//, ['races_id' => $races] );

ale wolałbym to ORMem zrobić....

0

z bindowaniem musisz zrobić coś takiego ( nie znam innego sposobu )

$binded  = str_repeat('?,', count($races) - 1) . '?';

        $sql = "select  p.[day] as day, sum(p.water) as water, sum(p.feed) as feed, sum(p.weight) as weight, sum(p.downs) as downs
                    from dbo.parameters p left join dbo.configurations c on c.id = p.configuration_id
                    inner join (
                        select race_id, max(date_from) as MaxDate
                        from dbo.configurations
                        group by race_id
                    ) tm on c.race_id = tm.race_id and c.date_from = tm.MaxDate
                    where c.race_id in ($binded) 
                    group by p.[day]
                    order by 4";


        $configuration = DB::select( $sql, $races );

W sumie też chętnie bym poznał sposób na wyciągnięcie temu podobnych via ORM

1 użytkowników online, w tym zalogowanych: 0, gości: 1