I got Unknown column error on having with count - laravel

In Laravel 6 I have a request of ads with related images count
$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);
and I see sql request ad_images_count field:
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
and it works for me with valid value in ad_images_count.
I need to set filter to show only ads with images and I added a scope in App Model :
public function scopeImagesCount($query, bool $check_images_count)
{
if ($check_images_count) {
return $query->where('ad_images_count', '>', 0);
}
return $query;
}
But if to uncoment line in the request :
//->imagesCount(true)
I got error :
MODIFIED BLOCK :
With request in which I commented ad_images_count subquery:
$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);
I modified scope with logging:
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;
}
And I see logging and Unknown column error in log file:
[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)
In resulting sql no subquery with ad_images_count
What is wrong?
MODIFIED BLOCK # 2:
If to comment imagesCount with request
$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);
I see sql generated :
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
with ad_images_count field having valid value
If to uncomment imagesCount with scope:
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;
}
I got error :
[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)
I tried to use addSelect - the same error.
looks like in having must subquery repeated, but not column name.
How?
MODIFIED BLOCK # 3 : 
I try to use having :
$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)
but I got error :
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
Looks like sda_ads.id is invalid condition. Which kind of wrapping does it need ?
I also tried without “`” symbol wrapping as :
->havingRaw(' ( SELECT count(*) '.
' FROM `'.$prefix.'ad_images'.'` '.
' WHERE '.$prefix.'ad_images.ad_id = '.$prefix.'ads.id ) > ?', [0])
and got :
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
In my database ads-backend-api I have sda_ads table with id field.
“sda_” is db prefix in database configuration.
Which way is right ?
Thanks!

In your scope you are directly requesting 'ad_image_count' alais but you have to make alias first like you did in raw query
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;
}

Related

I have no data with joined ad_categories table

In laravel 8 I make request with condition on joined ad_categories table :
$adsCategories = [1,2,3,4,6,7,8];
$data = Ad
::whereDate('expire_date', '>=', $date_start)
->whereDate('expire_date', '<', $date_end)
->orderBy($order_by, $order_direction)
->with('adCategories')
->with('creator')
->withCount('adLocations')
->leftJoin('ad_categories', 'ad_categories.ad_id', '=', 'ads.id')
->whereIn('ad_categories.category_id', $adsCategories)
->get();
and tracing sql :
SELECT `ads`.*, ( SELECT count(*)
FROM `ad_locations`
WHERE `ads`.`id` = `ad_locations`.`ad_id`) AS `ad_locations_count`
FROM `ads`
LEFT JOIN `ad_categories` on `ad_categories`.`ad_id` = `ads`.`id`
WHERE date(`expire_date`) >= '2021-04-01' AND date(`expire_date`) < '2021-05-01' AND `ad_categories`.`category_id` in ('1', '2', '3', '4', '6', '7', '8')
ORDER BY `expire_date` asc, `price` desc
I got no rows returned, but in database I see ralated rows :
Manually removing rows with ad_categories.category_id` :
SELECT `ads`.*, ( SELECT count(*)
FROM `ad_locations`
WHERE `ads`.`id` = `ad_locations`.`ad_id`) AS `ad_locations_count`
FROM `ads`
LEFT JOIN `ad_categories` on `ad_categories`.`ad_id` = `ads`.`id`
WHERE date(`expire_date`) >= '2021-04-01' AND date(`expire_date`) < '2021-05-01'
ORDER BY `expire_date` asc, `price` desc
I got all data I need.
What is wrong ?
Thanks!
use select...
$data = Ad
::whereDate('expire_date', '>=', $date_start)
->whereDate('expire_date', '<', $date_end)
->orderBy($order_by, $order_direction)
->with('adCategories')
->with('creator')
->withCount('adLocations')
->leftJoin('ad_categories', 'ad_categories.ad_id', '=', 'ads.id')
->whereIn('ad_categories.category_id', $adsCategories)
->select('ads.*', 'ad_categories.*') // <- add this line of code
->get();

Laravel Query Builder: Using `Case` with `Joins`

I am trying to replicate the following psql query in laravel:
SELECT
DISTINCT
I.id,
T.id,
T.name,
I.first_name,
I.middle_name,
I.last_name,
I.dob,
CASE WHEN NOT E.email IS NULL THEN '<<' ELSE '' END
FROM individuals AS I
LEFT JOIN titles AS T ON I.title_id = T.ID
LEFT JOIN individuals_emails_map AS IEM ON IEM.individual_id = I.id
LEFT JOIN emails AS E ON E.id = IEM.email_id;
When I use the query builder and write:
DB::table('individuals AS I')
->join('titles AS T', 'T.id', '=', 'I.title_id')
->leftjoin('individuals_emails_map AS IEM', 'IEM.individual_id', '=', 'I.id')
->leftjoin('emails AS E', 'E.id', '=', 'IEM.email_id')
->distinct('I.title_id', 'T.name', 'I.first_name', 'I.middle_name', 'I.last_name', 'I.dob')
->select('T.id','T.name', 'I.first_name','I.middle_name','I.last_name','I.dob')
->get();
... it works fine, however when I try and insert the CASE line:
DB::table('individuals AS I')
->join('titles AS T', 'T.id', '=', 'I.title_id')
->leftjoin('individuals_emails_map AS IEM', 'IEM.individual_id', '=', 'I.id')
->leftjoin('emails AS E', 'E.id', '=', 'IEM.email_id')
->distinct('I.title_id', 'T.name', 'I.first_name', 'I.middle_name', 'I.last_name', 'I.dob')
->select('T.id','T.name', 'I.first_name','I.middle_name','I.last_name','I.dob',
DB::raw("CASE WHEN NOT E.email IS NULL THEN '<<' ELSE '' END"))
->get();
... I get the following error:
Undefined table: 7 ERROR: missing FROM-clause entry for table "e"
What am I doing wrong?
I think that the problem in your case statement:
DB::raw("CASE WHEN NOT E.email IS NULL THEN '<<' ELSE '' END"))
it should be:
DB::raw('case WHEN E.email is Not NULL THEN "<<" Else " " END resultEmail'))

Laravel having query

This is my query:
Order::query()
->join('dispatcher_contractor_pays', function ($join) {
$join->on('orders.id', '=', 'dispatcher_contractor_pays.order_id')
->where('dispatcher_contractor_pays.contractor_type', '=', Contractor::class);
})
->join('order_workers_value_added', function ($join) {
$join->on('orders.id', '=', 'order_workers_value_added.order_id')
->where('order_workers_value_added.worker_type', '=', Contractor::class);
})
->having('orders.amount', '>', DB::raw('SUM(order_workers_value_added.amount)
+ SUM(dispatcher_contractor_pays.sum)'));
And get error:
"SQLSTATE[42S22]: Column not found: 1054 Unknown column 'orders.amount' in 'having clause' (SQL: select count(*) as aggregate from `orders` inner join `dispatcher_contractor_pays` on `orders`.`id` = `dispatcher_contractor_pays`.`order_id` and `dispatcher_contractor_pays`.`contractor_type` = Modules\Dispatcher\Entities\Directories\Contractor inner join `order_workers_value_added` on `orders`.`id` = `order_workers_value_added`.`order_id` and `order_workers_value_added`.`worker_type` = Modules\Dispatcher\Entities\Directories\Contractor where `status` not in (open) and `orders`.`contractor_id` = 13 and `domain_id` = 1 and exists (select * from `dispatcher_contractors` inner join `order_workers` on `dispatcher_contractors`.`id` = `order_workers`.`worker_id` where `orders`.`id` = `order_workers`.`order_id` and `order_workers`.`worker_type` = Modules\Dispatcher\Entities\Directories\Contractor and `dispatcher_contractors`.`deleted_at` is null) and `orders`.`deleted_at` is null having `orders`.`amount` > SUM(order_workers_value_added.amount) + SUM(dispatcher_contractor_pays.sum))"
What am I doing wrong?
Tables structure
orders : |id,amount,status, e.t.c |
dispatcher_contractor_pays: |id,date,sum,order_id,contractor_type, e.t.c |
order_workers_value_added: |id,amount,order_id,worker_type,worker_id, e.t.c |

how to create select join multiple condition in laravel 5.3

how to create select join multiple condition in laravel 5.3
SQL SELECT Statement.
SELECT table_1.column_1
,table_2.column_1
,table_3.column_1
FROM table_1
LEFT JOIN table_2
ON table_1.column_1 = table_2.column_1
LEFT JOIN table_3
ON table_1.column_2 = table_3.column_2
AND table_3.column_3 <= NOW()
AND ( table_3.column_4 >= NOW()
OR table_3.column_4 = 0
)
WHERE table_1.column_1 = '0000000001'
I want to convert SQL Statement to laravel select.
I try.
$result = DB::table('table_1')
->select('table_1.column_1', 'table_2.column_1', 'table_3.column_1')
->leftJoin('table_1', 'table_1.column_1', '=', 'table_2.column_1')
->leftJoin('table_3', 'table_1.column_2', '=', 'table_3.column_2')
->where('table_1', $_POST['id'])
->get();
DB::table('table_1')
->select('table_1.column_1', 'table_2.column_1', 'table_3.column_1')
->leftJoin('table_1', 'table_1.column_1', '=', 'table_2.column_1')
->leftJoin('table_3', 'table_1.column_2', '=', 'table_3.column_2')
->where('table_1.column_1', $_POST['id'])
->where('table_3.column_3','>=', NOW())
->where(function($query) {
$query->where('table_3.column_4', '>=', NOW())
->orWhere('table_3.column_4','0');
})
->get();

Laravel 5.3 Join on Field Value

This Laravel Model Query
PostModel::select('posts.*', 'users.name', 'users.user_fullname', 'users.user_gender', 'users.user_picture', 'users.user_picture_id', 'users.user_cover','users.user_cover_id', 'users.user_verified', 'users.user_pinned_post', 'pages.*', 'groups.group_name', 'groups.group_picture_id', 'groups.group_cover_id', 'groups.group_title', 'groups.group_admin', 'groups.group_pinned_post')
->leftjoin('users',function($flj){
$flj->on('posts.user_id', '=' ,'users.id')
->where('posts.user_type','=','user');
})
->leftjoin('pages',function ($slj){
$slj->on('posts.user_id', '=', 'pages.page_id')
->where('posts.user_type','=','page');
})
->leftjoin('groups',function ($tlj){
$tlj->on('posts.in_group','=',1)
->whereColumn('posts.group_id', '=', 'groups.group_id');
})
->whereRaw('NOT (users.name <=> NULL AND pages.page_name <=> NULL)')
->where('posts.post_id','=',$id)->get();
When Query Run Then Give me this Error
SQLSTATE[42S22]: Column not found: 1054 Unknown column '1' in 'on clause' (SQL: select `posts`.*, `users`.`name`, `users`.`user_fullname`, `users`.`user_gender`, `users`.`user_picture`, `users`.`user_picture_id`, `users`.`user_cover`, `users`.`user_cover_id`, `users`.`user_verified`, `users`.`user_pinned_post`, `pages`.*, `groups`.`group_name`, `groups`.`group_picture_id`, `groups`.`group_cover_id`, `groups`.`group_title`, `groups`.`group_admin`, `groups`.`group_pinned_post` from `posts` left join `users` on `posts`.`user_id` = `users`.`id` and `posts`.`user_type` = user left join `pages` on `posts`.`user_id` = `pages`.`page_id` and `posts`.`user_type` = page left join `groups` on `posts`.`in_group` = `1` and `posts`.`group_id` = `groups`.`group_id` where NOT (users.name <=> NULL AND pages.page_name <=> NULL) and `posts`.`post_id` = 360)
If i run this query direct on database no error
Query is
select `posts`.*, `users`.`name`, `users`.`user_fullname`, `users`.`user_gender`, `users`.`user_picture`, `users`.`user_picture_id`, `users`.`user_cover`, `users`.`user_cover_id`, `users`.`user_verified`, `users`.`user_pinned_post`, `pages`.*, `groups`.`group_name`, `groups`.`group_picture_id`, `groups`.`group_cover_id`, `groups`.`group_title`, `groups`.`group_admin`, `groups`.`group_pinned_post` from `posts` left join `users` on `posts`.`user_id` = `users`.`id` and `posts`.`user_type` = 'user' left join `pages` on `posts`.`user_id` = `pages`.`page_id` and `posts`.`user_type` = 'page' left join `groups` on `posts`.`in_group` = 1 and `posts`.`group_id` = `groups`.`group_id` where NOT (users.name <=> NULL AND pages.page_name <=> NULL) and `posts`.`post_id` = 360
And how to use where not in laravel??
Thanks's
You can replace
->whereRaw('NOT (users.name <=> NULL AND pages.page_name <=> NULL)')
with
->whereNotNull('users.name')
->whereNotNull('pages.page_name')
Edit:
Replace this
->leftjoin('groups',function ($tlj){
$tlj->on('posts.in_group','=',1)
->whereColumn('posts.group_id', '=', 'groups.group_id');
with
->leftjoin('groups',function ($tlj){
$tlj->on('posts.group_id','=', 'groups.group_id');
And put the in_group before your ->whereNotNull()
->where('posts.in_group', '=', 1)

Resources