Модель Codeigniter с запросом JOIN QueryBuilder

Действительно новичок в работе с моделью CI4 и изо всех сил пытается адаптировать мои существующие запросы MySQL JOIN для работы с примерами в его руководстве пользователя.

Я адаптировал часть своего кода так:

    public function brand_name($brand_name_slug)
    {
        return $this->asArray()
                    ->where('availability', 'in stock')
                    ->where('sku !=', '')
                    ->where('brand_name_slug', $brand_name_slug)
                    ->groupBy('gtin')
                    ->orderBy('brand_name, subbrand_name, product, size, unit')
                    ->findAll();
    }

Это работает нормально. Я просмотрел примеры и понял, что могу добавить код ->table('shop a'), и он все еще работает, но мне также нужно добавить следующий оператор JOIN:

JOIN (SELECT gtin, MIN(sale_price) AS sale_price FROM shop GROUP BY gtin) AS b ON a.gtin = b.gtin AND a.sale_price = b.sale_price

Как только я добавляю ->join('shop b', 'a.gtin = b.gtin and a.sale_price = b.sale_price'), я получаю сообщение об ошибке «404 — файл не найден».

Когда я просматриваю все примеры соединений CI4 и адаптирую свой код, мой цикл foreach($shop as $row) генерирует ошибку «Упс...», потому что они заканчиваются на getResult() или getResultArray вместо findAll().

Каков путь вперед, и мне нужно изменить мой цикл foreach.

Полный оператор MySQL:

SELECT * FROM shop a JOIN (SELECT gtin, MIN(sale_price) AS sale_price FROM shop GROUP BY gtin) AS b ON a.gtin = b.gtin AND a.sale_price = b.sale_price WHERE availability = 'in stock' AND sku != '' AND brand_name_slug = $brand_name_slug GROUP BY gtin ORDER BY brand_name, subbrand_name, product, size

person seixwebdev    schedule 02.06.2020    source источник
comment
Никогда не используйте SELECT *   -  person Strawberry    schedule 03.06.2020
comment
Кроме того, при отсутствии каких-либо агрегатирующих функций предложение GROUP BY НИКОГДА не подходит. Я бы сказал, что всегда используйте DISTINCT, если вам нужны четкие результаты, но, очевидно, DISTINCT не имеет смысла в контексте SELECT *, поэтому вам нужно выяснить, чего вы на самом деле хотите.   -  person Strawberry    schedule 03.06.2020


Ответы (3)


У построителей запросов есть свои ограничения. Вот почему существует метод запроса. Если у вас есть сложный запрос, я бы посоветовал вам просто использовать $this->query();.
Это позволит вам тратить меньше времени и усилий на преобразование того, что, как вы знаете, уже работает. И вдобавок ко всему, при преобразовании сложных запросов вы обычно в конечном итоге используете построитель запросов, но с большой частью вашего SQL в нем.

В вашей модели, расширяющей CodeIgniter\Model :

    $query = $this->db->query("SELECT * FROM shop a JOIN (SELECT gtin, MIN(sale_price) AS sale_price FROM shop GROUP BY gtin) AS b ON a.gtin = b.gtin AND a.sale_price = b.sale_price WHERE availability = 'in stock' AND sku != '' AND brand_name_slug = \$brand_name_slug GROUP BY gtin ORDER BY brand_name, subbrand_name, product, size");

    // your array result
    $result_array = $query->getResultArray();
    // your object result
    $result_object = $query->getResult();
person ViLar    schedule 03.06.2020

Класс BaseBuilder в Codeigniter ожидает, что первым параметром соединения будет имя таблицы. Поэтому попробуйте передать имя таблицы и присоединиться к нему по имени самой таблицы. Я лично не использовал псевдонимы таблиц, поэтому могу ошибаться.

Ниже приведены параметры, ожидаемые запросом JOIN:

    public function join(string $table, string $cond, string $type = '', bool $escape = null)

Здесь он ожидает, что первым именем будет таблица, поэтому попробуйте напрямую изменить псевдонимы для имени таблицы.

Для вашей второй части запроса было бы лучше, если бы вы могли показать всю ошибку, а не просто публиковать первую ошибку.

person Dhaval Chheda    schedule 03.06.2020

В итоге удалось разобраться:

    public function brand_name($brand_name_slug)
    {
        return $this
                    ->db
                    ->table('shop a')
                    ->select()
                    ->join('(SELECT sku, MIN(sale_price) AS sale_price FROM shop GROUP BY sku) AS b', 'a.sku = b.sku AND a.sale_price = b.sale_price')
                    ->where('availability', 'in stock')
                    ->where('a.sku !=', '')
                    ->where('brand_name_slug', $brand_name_slug)
                    ->groupBy('a.sku')
                    ->orderBy('brand_name, subbrand_name, product, size, unit')
                    ->get()
                    ->getResult();
    }

Спасибо за все ваши указатели!

person seixwebdev    schedule 03.06.2020