PHP Красноречивое выравнивание вложенных селекторов `whereHas`? - PullRequest
0 голосов
/ 24 марта 2020

Мне поручили оптимизировать какой-то старый php проект для новой компании, в которой я работаю. Некоторый вызов API занимает почти 20 секунд, что слишком долго, и я отследил проблему до некоторого sql, сгенерированного в проекте. Он имеет несколько вложенных exists 'и был (я считаю) сгенерирован следующим кодом:

return Workstation::whereHas('productionSteps', function ($qp) {
    $qp->whereHas('subSteps', function ($qs) {
        $qs->whereHas('position', function ($qpr) {
            $qpr->where('ProjectId', $this->id);
        });
    });
})->get();

результирующий запрос:

SELECT *
from `workstations`
where EXISTS (
    select * 
    from `productionsteps` 
    where `productionsteps`.`UsedWorkStationId` = `workstations`.`Id` 
    and exists (
        select * 
        from `substeps` 
        where `substeps`.`ParentStepId` = `productionsteps`.`Id` 
        and exists (
                select * 
            from `positions` 
            where `substeps`.`PositionId` = `positions`.`Id` 
            and `ProjectId` = "some id"
        )
    )
);

Поэтому я оптимизировал запрос только используйте один exists

SELECT *
from `workstations`
where EXISTS (
    select * 
    from `productionsteps`, `substeps`, `positions`
    where `productionsteps`.`UsedWorkStationId` = `workstations`.`Id` 
    AND `substeps`.`ParentStepId` = `productionsteps`.`Id` 
    and `substeps`.`PositionId` = `positions`.`Id` 
    and `ProjectId` = "some id"
);

Однако я не уверен, как обновить код php.

Так как мне это сделать в php?

Ответы [ 2 ]

1 голос
/ 24 марта 2020

Это будет моя лучшая догадка, судя по документации:

return Workstation::whereExists(function($query) {
    $query
        ->join('productionsteps', 'UsedWorkStationId', '=', 'workstations.Id')
        ->join('substeps', 'ParentStepId', '=', 'productionsteps.Id')
        ->join('positions', 'PositionId', 'positions.Id')
        ->where('ProjectId', $this->id);
})->get();
0 голосов
/ 24 марта 2020

Я не знаю красноречивый способ сделать это; Поскольку есть много таблиц, с которыми вы работаете, хотя я бы использовал широкую select вместо:

DB::select("
SELECT *
from `workstations`
where EXISTS (
    select * 
    from `productionsteps`, `substeps`, `positions`
    where `productionsteps`.`UsedWorkStationId` = `workstations`.`Id` 
    AND `substeps`.`ParentStepId` = `productionsteps`.`Id` 
    and `substeps`.`PositionId` = `positions`.`Id` 
    and `ProjectId` = ?
);
", ['some id']); // array is for prepared parameters binding
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...