Laravel Query Builder Statement return no result, but sql statement does - sql

Laravel Query Builder
$data = CustomerPrepaid
::join('pos_sales', 'customer_prepaid.customer_id', '=', 'pos_sales.customer_id')
->join('pos_sales_product', 'pos_sales.pos_sales_code', '=', 'pos_sales_product.pos_sales_code')
->where('pos_sales_product.product_id', 'customer_prepaid.product_id')
->select('customer_prepaid.customer_id', 'customer_prepaid.created_at',
'pos_sales_product.pos_sales_product_code as reference_no',
'customer_prepaid.product_id', 'customer_prepaid.balance',
'last_used', 'expiry_date', 'customer_prepaid.amount as price')
->offset(($page-1)*$limit)->limit($limit)->get();
SQL
SELECT customer_prepaid.customer_id, customer_prepaid.created_at as purchase_date,
pos_sales_product.pos_sales_product_code as reference_no, customer_prepaid.product_id,
customer_prepaid.balance, customer_prepaid.amount*customer_prepaid.balance as value,
last_used, expiry_date, customer_prepaid.amount as price,
customer_prepaid.amount*customer_prepaid.balance as total
FROM customer_prepaid
JOIN pos_sales ON customer_prepaid.customer_id = pos_sales.customer_id
JOIN pos_sales_product ON pos_sales.pos_sales_code = pos_sales_product.pos_sales_code
WHERE pos_sales_product.product_id = customer_prepaid.product_id
The resulting SQL executed on the server returns the right result, but I get no eloquent result, why might that be?

Oh gosh, took me forever to realize you misused ->where.
Change your ->where to ->whereColumn:
$data = CustomerPrepaid
::join('pos_sales', 'customer_prepaid.customer_id', '=', 'pos_sales.customer_id')
->join('pos_sales_product', 'pos_sales.pos_sales_code', '=', 'pos_sales_product.pos_sales_code')
->whereColumn('pos_sales_product.product_id', 'customer_prepaid.product_id')
->select(
'customer_prepaid.customer_id',
'customer_prepaid.created_at',
'pos_sales_product.pos_sales_product_code as reference_no',
'customer_prepaid.product_id', 'customer_prepaid.balance',
'last_used', 'expiry_date', 'customer_prepaid.amount as price'
)
->offset(($page-1)*$limit)
->limit($limit)
->get();
You have to use whereColumn instead of where to make column comparison. Else it's expecting a third parameter value to be set.
Check the documentation on how to use whereColumn: https://laravel.com/docs/5.5/queries#where-clauses

Related

Laravel query builder left join from subquery

I'm using Laravel query builder and trying to do something like this:
$builder = DB::table('mainTable')->where("mainTable.id", "=", 111);
$builder->leftJoinSub(
DB::table('table2')
->where('table2.id', '=', DB::raw("mainTable.subtableId"))
->where('table2.region', '=', DB::raw("mainTable.region"))
->orderBy('table2.someOrder', 'DESC')
->select('kamery2.id')
->first(),
'myId',
'table2.id',
'=',
'myId'
);
And I'm getting
The multi-part identifier "mainTable.subtableId" could not be bound.
However when I write it with DB::raw('...') it works.
$builder->leftJoin(
'table2',
'table2.id',
'=',
DB::Raw("...")
);
So I'm trying to find out what I'm doing wrong. Did I make a syntactic mistake only? Or Laravel query's builder doesn't allow what I want to achieve and I have to use ->leftJoin(.... DB::raw() ) ?

exists query does not return relevant result

I have a Laravel application with this Eloquent query:
$products = Product::where('name', 'LIKE', "%{$value}%")
->whereHas('categories', function($q) {
$q->where( 'slug', 'tonery-cartridge' );
})->with('manufacturer')
->with('sm_image')
->orderBy('created_at','DESC')
->take(10)
->get();
This code generates the sql command like:
select * from `products` where `name` LIKE '%can%'
and exists (
select * from `categories` inner join `category_product`
on `categories`.`id` = `category_product`.`category_id`
where `products`.`id` = `category_product`.`product_id`
and `slug` = 'tonery-cartridge'
)
order by `created_at` desc limit 10
I am sure there are products which name contains "can" string and which belongs to the category with slug "tonery-cartridge". Why this query returns an empty result? If I try to make inner join sql manually it works well as on the screenshot below:
I think that your queries are not equivalent. The SQL output from laravel does not join tables in it's FROM clause, but in your manually constructed SQL statement you do a lot of inner joins in your FROM clause and on the resulting table you perform your operations, which is not true for the former.
Try the following
DB::table('products')
->join('category_product', 'category_product.product_id', '=', 'products.id')
->join('categories', 'category_product.category_id', '=', 'categories.id')
->whereRaw('products.name LIKE %can% AND categories.slug = "tonery-cartridge"')
->select('products.name', 'categories.slug')
->orderBy('created_at','DESC')
->take(10)
->get()
If you want to avoid using whereRaw, you can try the following.
DB::table('products')
->join('category_product', 'category_product.product_id', '=', 'products.id')
->join('categories', 'category_product.category_id', '=', 'categories.id')
->where([
['products.name, 'LIKE', '%' . $value . '%'],
['categories.slug', '=', 'tonery-cartridge']])
->select('products.name', 'categories.slug')
->orderBy('created_at','DESC')
->take(10)
->get()
HTH
This could be one of the solutions
$category = Category::where( 'slug', 'tonery-cartridge' )->first();
$products = $category->products()
->where('name', 'LIKE', "%{$value}%")
->with('manufacturer')
->with('sm_image')
->latest()
->take(10)
->get();

How to get number of customer and total amount for time range?

I want to have the result of the table below, I have two tables, one for the clients and one for the transactions made by the clients.Someone can help me to achieve that!Thank's in advance
here is what i want to return
This the query i write to get the result.
$customers_trans = DB::table('contacts as c')
->select(
DB::raw('SUM(tr.final_total) AS total_customer'),
DB::raw('COUNT(c.id) AS customercount'),
DB::raw('COUNT(c.id) AS average')
)
->whereBetween('tr.transaction_date', [$date_debut, $date_fin])
->groupBy('c.id')
->join('transactions as tr', 'tr.contact_id', '=', 'c.id')
->get()->toArray();
I think this is what you want:
$customers_trans = DB::table('contacts as c')
->select(
DB::raw('SUM(tr.final_total) AS total_customer'),
DB::raw('COUNT(*) AS customer_count'),
DB::raw('AVG(tr.final_total) AS average')
)
->join('transactions as tr', 'tr.contact_id', '=', 'c.id')
->whereBetween('tr.transaction_date', [$date_debut, $date_fin])
->groupByRaw('HOUR(tr.transaction_date)')
->get()
->toArray();

cannot group with eloquent with PostreSQL

Here's my Eloquent query:
$visits = Visit::orderBy('date', 'desc')->groupBy('user_id')->get(['date', 'user_id']);
But posgreSQL is refusing the query, telling me:
SQLSTATE[42803]: Grouping error: 7 ERROR: column "visits.date" must appear in the GROUP BY clause or be used in an aggregate function
LINE 1: select "date", "user_id" from "visits" group by...
the same stuff works on MySQL when I disable ONLY_FULLY_GROUP_BY
what can I do to make it work? It would be great if I didn't have to edit configs, just the code.
This selects the latest date for each user_id:
$sub = Visit::select('user_id', DB::raw('max("date") "date"'))->groupBy('user_id');
$sql = '(' . $sub->toSql() . ') as "sub"';
$visits = Visit::join(DB::raw($sql), function($join) {
$join->on('visits.user_id', 'sub.user_id')
->on('visits.date', 'sub.date');
})->orderBy('visits.date', 'desc')->get(['visits.date', 'visits.user_id']);
If there are multiple visits for a user_id and date combination, the query returns all of them. Removing the duplicates is possible, but makes the query more complex.
It's easier to remove them afterwards:
$visits = $visits->unique('user_id');
Using postgre sql you could use distinct on user_id and order your date column to pick latest date per user_id, In laravel you could raw expression
$visits = Visit::select(DB::raw('distinct on (user_id)'), 'date')
->orderBy('date', 'desc')
->get();
Demo

Use SQL query in Laravel

this is my sql Query:
SELECT DISTINCT batch_job_instance.JOB_NAME, MAX(batch_job_execution.CREATE_TIME) AS CREATED_TIME, batch_job_execution.END_TIME, batch_job_execution.STATUS FROM `batch_job_execution` INNER JOIN batch_job_instance ON batch_job_execution.JOB_INSTANCE_ID = batch_job_instance.JOB_INSTANCE_ID WHERE batch_job_execution.CREATE_TIME LIKE '%2016-12-05%' GROUP BY batch_job_instance.JOB_INSTANCE_ID ORDER BY MAX(batch_job_execution.CREATE_TIME) DESC
my Question, how i use that query in laravel? i am new in laravel, can someone help me? i need this for my project Thanks :)
You can run this SQL query as ot is if you had problem in converting in laravel format.
You can use :
DB::select(DB::RAW(your_sql_query)):
Hope this will help.
You can create a function within your model and query the data using the bellow format
public static function getJobs()
{
$jobs = DB::table('batch_job_execution')
->select(
DB::raw('
DISTINCT batch_job_instance.JOB_NAME,
MAX(batch_job_execution.CREATE_TIME) AS CREATED_TIME,
batch_job_execution.END_TIME,
batch_job_execution.STATUS
'
)
)
->join('batch_job_instance', 'batch_job_execution.JOB_INSTANCE_ID', '=', 'batch_job_instance.JOB_INSTANCE_ID')
->where('batch_job_execution', 'LIKE', '%2016-12-05%')
->groupBy('batch_job_instance.JOB_INSTANCE_ID')
->orderBy(DB::raw('MAX(batch_job_execution.CREATE_TIME)'),'DESC')
->get();
// ->toSql();
return $jobs;
}