Я получил Неизвестную ошибку столбца при наличии с подсчетом - PullRequest
0 голосов
/ 30 января 2020

В Laravel 6 У меня есть запрос объявлений с количеством связанных изображений

$ads = Ad
    ->getByTitle($this->filter_title)
    ->onlyNoneInfo()
    ->getByStatus('A')
    //->imagesCount(true)
    ->getUserByStatus('A')
    ->leftJoin('users', 'users.id', '=', 'ads.creator_id')
    ->orderBy($this->order_by, $this->order_direction)

    ->select(
        'ads.*',
        'users.name as creator_username',
        'users.email as creator_email',
        'users.phone as creator_phone'
    )->addSelect(['ad_images_count' => AdImage
        ::selectRaw('count(*)')
        ->whereColumn('ad_images.ad_id', 'ads.id')
    ])

    ->offset($limit_start)
    ->take($ads_per_page)
    ->distinct()
    ->paginate($ads_per_page);

, и я вижу поле sql request ad_images_count:

   SELECT distinct `sda_ads`.*, `sda_users`.`name`     AS `creator_username`, `sda_users`.`email`     AS `creator_email`, `sda_users`.`phone`     AS `creator_phone`, (  SELECT count(*) 
    FROM `sda_ad_images` 
    WHERE `sda_ad_images`.`ad_id` = `sda_ads`.`id`)     AS `ad_images_count` 
    FROM `sda_ads` 
    LEFT JOIN `sda_users` on `sda_users`.`id` = `sda_ads`.`creator_id` 
    WHERE `ad_type` <> 'I'     AND `sda_ads`.`status` = 'A'     AND `sda_users`.`status` = 'A' 
    ORDER BY `price` asc limit 4 offset 0 

и оно у меня работает с действительным значением в ad_images_count. Мне нужно установить фильтр, чтобы показывать только рекламу с изображениями, и я добавил область в App Model:

public function scopeImagesCount($query, bool $check_images_count)
{
    if ($check_images_count) {
        return $query->where('ad_images_count', '>', 0);
    }
    return $query;
}

Но если раскомментировать строку в запросе:

//->imagesCount(true)

Я получил ошибка:

МОДИФИЦИРОВАННЫЙ БЛОК: С запросом, в котором я прокомментировал подзапрос ad_images_count:

$ads = Ad
    ::getByTitle($this->filter_title)
    ->onlyNoneInfo()
    ->getByStatus('A')
    ->getUserByStatus('A')
    ->imagesCount(true)
    ->leftJoin('users', 'users.id', '=', 'ads.creator_id')
    ->orderBy($this->order_by, $this->order_direction)

    ->select(
        'ads.*',
        'users.name as creator_username',
        'users.email as creator_email',
        'users.phone as creator_phone'
    )
    /*
    ->addSelect(['ad_images_count' => AdImage
        ::selectRaw('count(*)')
        ->whereColumn('ad_images.ad_id', 'ads.id')
    ])
    */
    ->offset($limit_start)
    ->take($ads_per_page)
    ->distinct()
    ->paginate($ads_per_page);

Я изменил область видения с ведением журнала:

public function scopeImagesCount($query, bool $check_images_count)
    {
        \Log::info('scopeImagesCount $check_images_count ::');
        \Log::info($check_images_count);

        if ($check_images_count) {
            \Log::info('CHECKING  ::');
            return $query->select(['ad_images_count' => AdImage
                ::selectRaw('count(*)')
                ->whereColumn('ad_images.ad_id', 'ads.id')
            ])->where('ad_images_count', '>', 0);
        }
        \Log::info('SKIPPED CHECKING  ::');
        return $query;
    }

И я вижу журнал и неизвестную ошибку столбца в файле журнала:

[2020-01-30 11:29:59] local.INFO: scopeImagesCount $check_images_count ::  
[2020-01-30 11:29:59] local.INFO: 1  
[2020-01-30 11:29:59] local.INFO: CHECKING  ::  
[2020-01-30 11:29:59] local.ERROR: SQLSTATE[42S22]: Column not found: 1054 Unknown column 'ad_images_count' in 'where clause' (SQL: select count(*) as aggregate from `sda_ads` left join `sda_users` on `sda_users`.`id` = `sda_ads`.`creator_id` where `ad_type` <> I and `sda_ads`.`status` = A and `sda_users`.`status` = A and `ad_images_count` > 0) {"exception":"[object] (Illuminate\\Database\\QueryException(code: 42S22): SQLSTATE[42S22]: Column not found: 1054 Unknown column 'ad_images_count' in 'where clause' (SQL: select count(*) as aggregate from `sda_ads` left join `sda_users` on `sda_users`.`id` = `sda_ads`.`creator_id` where `ad_type` <> I and `sda_ads`.`status` = A and `sda_users`.`status` = A and `ad_images_count` > 0) at /mnt/_work_sdb8/wwwroot/lar/ads-backend-api/vendor/laravel/framework/src/Illuminate/Database/Connection.php:669)

В результате sql нет подзапроса с ad_images_count Что не так?

МОДИФИЦИРОВАННЫЙ БЛОК № 2:

Если комментировать imagesCount с запросом

        $ads = Ad
            ::getByTitle($this->filter_title)
            ->onlyNoneInfo()
            ->getByStatus('A')
            ->getUserByStatus('A')
//            ->imagesCount(true)
            ->leftJoin('users', 'users.id', '=', 'ads.creator_id')
            ->orderBy($this->order_by, $this->order_direction)

            ->select(
                'ads.*',
                'users.name as creator_username',
                'users.email as creator_email',
                'users.phone as creator_phone'
            )
            ->addSelect(['ad_images_count' => AdImage
                ::selectRaw('count(*)')
                ->whereColumn('ad_images.ad_id', 'ads.id')
            ])

            ->offset($limit_start)
            ->take($ads_per_page)
            ->distinct()
            ->paginate($ads_per_page);

Я вижу sql сгенерировано:

   SELECT distinct `sda_ads`.*, `sda_users`.`name`     AS `creator_username`, `sda_users`.`email`     AS `creator_email`, `sda_users`.`phone`     AS `creator_phone`, (  SELECT count(*) 
    FROM `sda_ad_images` 
    WHERE `sda_ad_images`.`ad_id` = `sda_ads`.`id`)     AS `ad_images_count` 
    FROM `sda_ads` 
    LEFT JOIN `sda_users` on `sda_users`.`id` = `sda_ads`.`creator_id` 
    WHERE `ad_type` <> 'I'     AND `sda_ads`.`status` = 'A'     AND `sda_users`.`status` = 'A' 
    ORDER BY `price` asc limit 4 offset 0 

с полем ad_images_count, имеющим действительное значение

Если раскомментировать imagesCount с областью действия:

    public function scopeImagesCount($query, bool $check_images_count)
    {
        \Log::info('scopeImagesCount $check_images_count ::');
        \Log::info($check_images_count);

        if ($check_images_count) {
            \Log::info('CHECKING  ::');
            return $query->select(['ad_images_count' => AdImage
//            return $query->addSelect(['ad_images_count' => AdImage
                ::selectRaw('count(*)')
                ->whereColumn('ad_images.ad_id', 'ads.id')
            ])->where('ad_images_count', '>', 0);
        }
        \Log::info('SKIPPED CHECKING  ::');
        return $query;
    }

Я получил ошибку:

[2020-01-31 15:27:37] local.ERROR: SQLSTATE[42S22]: Column not found: 1054 Unknown column 'ad_images_count' in 'where clause' (SQL: select count(*) as aggregate from `sda_ads` left join `sda_users` on `sda_users`.`id` = `sda_ads`.`creator_id` where `ad_type` <> I and `sda_ads`.`status` = A and `sda_users`.`status` = A and `ad_images_count` > 0) {"exception":"[object] (Illuminate\\Database\\QueryException(code: 42S22): SQLSTATE[42S22]: Column not found: 1054 Unknown column 'ad_images_count' in 'where clause' (SQL: select count(*) as aggregate from `sda_ads` left join `sda_users` on `sda_users`.`id` = `sda_ads`.`creator_id` where `ad_type` <> I and `sda_ads`.`status` = A and `sda_users`.`status` = A and `ad_images_count` > 0) at /mnt/_work_sdb8/wwwroot/lar/ads-backend-api/vendor/laravel/framework/src/Illuminate/Database/Connection.php:669)

Я пытался использовать addSelect - та же ошибка. Похоже на необходимость повторять подзапрос, но не имя столбца. Как?

МОДИФИЦИРОВАННЫЙ БЛОК № 3: Я пытаюсь использовать:

$prefix= DB::getTablePrefix();

$ads = Ad
    ::getByTitle($this->filter_title)
    ->onlyNoneInfo()
    ->getByStatus('A')
    ->getUserByStatus('A')
    ->leftJoin('users', 'users.id', '=', 'ads.creator_id')
    ->orderBy($this->order_by, $this->order_direction)

    ->select(
        'ads.*',
        'users.name as creator_username',
        'users.email as creator_email',
        'users.phone as creator_phone'
    )
    ->addSelect(['ad_images_count' => AdImage
        ::selectRaw('count(*)')
        ->whereColumn('ad_images.ad_id', 'ads.id')
    ])

    ->offset($limit_start)
    ->take($ads_per_page)


    ->havingRaw(' ( SELECT count(*) '.
        ' FROM `'.$prefix.'ad_images'.'` '.
        ' WHERE '.$prefix.'ad_images.ad_id = `'.$prefix.'ads`.`id` ) > ?', [0])
    ->paginate($ads_per_page)

, но я получил ошибку:

Unknown column 'ads-backend-api.sda_ads.id' in 'where clause' (SQL: 
select count(*) as aggregate from `sda_ads` left join `sda_users` on `sda_users`.`id` = `sda_ads`.`creator_id` where `ad_type` <> I and `sda_ads`.`status` = A and `sda_users`.`status` = A having  ( SELECT count(*)  FROM `sda_ad_images`  WHERE sda_ad_images.ad_id = `sda_ads`.`id` ) > 0

Похоже sda_ads. id недопустимое условие. Какой тип обтекания ему нужен?

Я также пробовал без переноса символа «` »как:

->havingRaw(' ( SELECT count(*) '.
    ' FROM `'.$prefix.'ad_images'.'` '.
    ' WHERE '.$prefix.'ad_images.ad_id = '.$prefix.'ads.id ) > ?', [0])

и получил:

Unknown column 'ads-backend-api.sda_ads.id' in 'where clause' (SQL: select count(*) as aggregate from `sda_ads` left join `sda_users` on `sda_users`.`id` = `sda_ads`.`creator_id` where `ad_type` <> I and `sda_ads`.`status` = A and `sda_users`.`status` = A having  ( SELECT count(*)  FROM `sda_ad_images`  WHERE sda_ad_images.ad_id = sda_ads.id ) > 0

В моей рекламе базы данных -backend-api У меня есть таблица sda_ads с полем id.

«sda_» - это префикс db в конфигурации базы данных.

Какой путь подходит?

Спасибо!

1 Ответ

2 голосов
/ 30 января 2020

В своей области вы напрямую запрашиваете alais 'ad_image_count', но сначала вам нужно создать псевдоним, как вы это делали в необработанном запросе

    public function scopeImagesCount($query, bool $check_images_count)
    {
      if ($check_images_count) {
        return $query->select(['ad_images_count' => AdImage
            ::selectRaw('count(*)')
            ->whereColumn('ad_images.ad_id', 'ads.id')
        ])->where('ad_images.ad_images_count', '>', 0);
     }
     return $query;
   }
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...