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

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();

Related

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();

Laravel query with where and where

I've trying to basically do two SQL requests into one laravel array.
These are my SQL
SELECT * FROM `transactions` WHERE `plan` LIKE '1050' ORDER BY `updated_at` DESC
SELECT * FROM `transactions` WHERE `user` LIKE '1050' ORDER BY `updated_at` DESC
I want to have all transaction that have "plan" == "1050" AND all transactions that have "user" == "1050" in one variable.
This is not working for me:
$ct=transactions::where('user',$user->id)
->orWhere('plan', $user->id)
->orderby('created_at',"asc")->get();
The context agnostic way to combine the results of two union compatible queries (such as yours) would be:
$result = transactions::where('plan', 'LIKE', $user->id)->orderBy('updated_at', 'DESC')
->union(
transactions::where('user', 'LIKE', $user->id)
->orderBy('updated_at', 'DESC')
)
->get();
This of course means that the results are ordered by plan then user. You can sort them by updated_at globally using the below function on the result:
$result = $result->sortBy('updated_at', 'DESC');
There's also a way to do it on the query level but I don't see much benefit since you're getting all the data anyway.
The above query should be functionally equivalent to:
$result = transactions::orWhere('plan', 'LIKE', $user->id)
->orWhere('user', 'LIKE', $user->id)
->orderBy('updated_at', 'DESC')
->get();
This will have the same results but in a different order than the union.

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

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

Join Statement using Query builder with multiple where clause

I have a Query builder statement below and I would want to introduce another condition to the query. However, I can not get this right.
This query works fine;
$content = DB::table('subscribed_services as a')
->join('scheduled_messages as b', 'a.id', '=', 'b.subscribed_services_id')
->join('subscription_services_msisdn as c', 'a.id', '=', 'c.subscribed_services_id')
->whereRaw('DATE(b.scheduled_at) = CURDATE()')
->selectRaw('b.message, c. phone_number, a.username, a.password')
->distinct()
->get();
I would want to introduce another where statement; this ->whereRaw('DATE(c.sent_time) != CURDATE()'). Meaning the query above should only pick values where subscription_services_msisdn.sent_time DATE(c.sent_time) IS NOT EQUAL to Current Date CURDATE().
Anyone lead me here. Regards.
You can chain as many where conditions as you want, so just add another whereRaw to the chain:
$content = DB::table('subscribed_services as a')
->join('scheduled_messages as b', 'a.id', '=', 'b.subscribed_services_id')
->join('subscription_services_msisdn as c', 'a.id', '=', 'c.subscribed_services_id')
->whereRaw('DATE(b.scheduled_at) = CURDATE()')
->whereRaw('DATE(c.sent_time) <> CURDATE()')
->selectRaw('b.message, c. phone_number, a.username, a.password')
->distinct()
->get();

Laravel list issue

I have below query which is directly linked to drop down. However, if I lists() with join() it gives
errors: ambiguous 'id'
Code:
Company::join('users', 'users.company_id', '=', 'companies.id')
->distinct()
->where('companies.name', 'NOT LIKE', '%XXXX%')
->lists('name', 'id');
What could be a solution with lists()? any help would be real help.
Both tables contain an id field. The solution here would be to prepend the table name to the id field that you want to list. For example:
Company::join('users', 'users.company_id', '=', 'companies.id')
->select(
'companies.name as companyName',
'companies.id as companyID'
)
->distinct()
->where('companies.name', 'NOT LIKE', '%XXXX%')
->lists('companyName', 'companyID');
The error showing because you id column in both of your table. I don't know which table's id you needed. In this answer I assume you don't need the id of user so I declared it as uid. So, there is only one column named id which is belong to companies table.
Company::join('users', 'users.company_id', '=', 'companies.id')
->distinct()
->where('companies.name', 'NOT LIKE', '%XXXX%')
->select('users.id as uid','companies.id','companies.name')
->lists('name', 'id');
Try this code:
DB::table('companies')->distinct()->join('users',function($join){
$join->on( 'users.company_id', '=', 'companies.id')
->where('companies.name', 'NOT LIKE', '% %');
}) ->lists('companies.name');
P.S. works fine for me