Count products that are bought together - php

I have made a query that counts how many products are bought together, but I don't want to have the products both ways in it
Code
DB::table(DB::raw('tenant_db.sales_data as b'))
->selectRaw('a.product_id as product_id, b.product_id as bought_with, count(*) as times_bought_together')
->join(DB::raw('tenant_db.sales_data as a'), function ($join){
$join->on('a.sale_id', '=', 'b.sale_id');
$join->on('a.product_id', '!=', 'b.product_id');
})
->groupBy('a.product_id', 'b.product_id');
Output
Product_id Bought_with times_bought_together'
52 24 3
24 52 3
So I only want to have it one time not twice, is that possible (based on quantity)?

Use < rather than !=:
$join->on('a.product_id', '<', 'b.product_id');

Related

How do i query percentages in a select tag

I am trying to get the percentages of the industry_id compared to the adtype_id. So the example below for industry id 2, It should be 1/3 and 2/3 for a total of 100%. I get the records 1 and 2 but how do i get the total count of industry id using this select query is what i am having trouble with. This part of the code is not correct select count(*) from ads This is giving output of all the records of the column i just want total record specific to the id of the industry id .
adtype_id industry_id
2 2
3 2
3 2
result i want: 1/3, 2/3
$intantype = Ad::
join('industries', 'industries.id', 'ads.industry_id')
->join('adtypes', 'adtypes.id', 'ads.adtype_id')
->where('ads.industry_id', $id)
->Select('ads.adtype_id',DB::raw('count(*) *100 / (select count(*) from ads) as total '), 'industryname')
->groupBy('adtype_id','industryname')
->get();

Laravel nesting where clause (Query Builder)

So i am confused on laravel nested queries.
I am trying to prepared a search function that filters the products that is in the sales_agreement table but also if the record has financing i want it to be filtered too.
Below is my sample.
(1) Table Products
id product_name price
1 car 500k
2 jeep 200k
3 motor 100k
4 bicycle 5k
(2) Sales Agreement
id product_id price financing
1 2 500k BPI
2 1 200k MetroBank
3 3 100k
Expected Output In my query
product_id product_name
2 jeep
1 car
4 bicycle
My Query
$result = DB::table('products')
->whereNotIn('id',function($q){
$q->select('product_id')->from('sales_agreement');
})->where('product_name','LIKE','%' . $get['q'] . '%')
->select('id','product_name')
->get();
This filters all of the products that is not in the sales_agreement table. But i also want to consider the items that has a Financing record in the sales_agreement table. In that point i dont have an idea how to do it.
Any comments/suggestion/answer will be much appreciated. Thanks !
You can try where null
$result = DB::table('products')
->whereNotIn('id',function($q){
$q->select('product_id')->from('sales_agreement')
->whereNull('financing');
})->where('product_name','LIKE','%' . $get['q'] . '%')
->select('id','product_name')
->get();
If you want to exclude the products that don't have financing record you can do a left join with additional clause
$result = DB::table('products as p')
->leftJoin('sales_agreement as s', function ($query) {
$query->on('p.id', '=', 's.product_id')
->whereNull('s.financing');
})
->whereNull('s.product_id')
->where('p.product_name', 'LIKE', '%' . $get['q'] . '%')
->select('p.id', 'p.product_name')
->get();

how to get highest 5 values from column?

I have products table with name and no_of_sell column..
I wanted to get highest 5 sold products based on no_of_sell column from products table.
how do i use it with query builder?
$propular_products = DB::table('users')
->join('products','products.auth_id','users.id')
->select('products.*')
->orderBy('products.no_of_sell', 'desc')
->where('products.status','=','1')
->paginate(5);
suppose products table:
name no_of_sell
x 6
y 9
z 10
t 23
u 3
h 11
r 5
i wanted to find
products list of 5 max no_of_sell ie, x y z t h
So if I understand it correctly in the column no_of_sell is a int. I should write it as follow :
$best_sell = DB::table('products')
->orderBy('no_of_sell', 'desc')
->limit(5)
->where('products.status','=','1')
->paginate(4)
->get();
https://laravel.com/docs/5.4/queries#retrieving-results
https://laravel.com/docs/5.4/queries#ordering-grouping-limit-and-offset
$best_sell = DB::table('products')
->select('no_of_sell')
->where('products.status','=','1')
->orderBy('no_of_sell', 'desc')
->paginate(4);
$best_sell = DB::table('products')
->select() // your selection criteria
->where('products.status','=','1')
->take(5)->get();

Average of a calculated second average in Laravel Query Builder

I have 3 tables : Appointments, Reviews, Review_ratings
Each review_ratings has a rating value. Each review has many review_ratings and finally, eeach appointment has many reviews.
What I am trying to do is to calculated the average of review_ratings per review, and then calculate the average of reviews total ratings and see if it is higher than a specific int.
Exemple:
Apointment id : 1, has 2 Reviews, each review has review_rating one of 4 and 3 and review rating number 2 of 5 and 5.
AVG(review_ratings) should return the average between average(5,5) and average(4,3) which is 3.5 then AVG(the_first_avg) should return average (3.5,5) which is 4.25.
My last tested query is :
if($minRating > 0){
$search->join('appointments','appointments.doctor_id','users.id')
->join('reviews','reviews.appointment_id','appointments.id')
->join('review_ratings','review_ratings.review_id','reviews.id')
->addSelect(array('review_ratings.id',
DB::raw('AVG(review_ratings.rating) as review_ratings_count')
))
->addSelect(
DB::raw('AVG(review_ratings_count) as ratings_avg')
)
->where('ratings_avg','>=',$minRating)
;
}
The error I'm getting is
Column not found: 1054 Unknown column 'review_ratings_count' in 'field
list'
I found the solution to be much simpler that my code, and using AVG(name_of_column) rather than using the 'AS' value
->selectRaw('AVG(review_ratings.rating) as overall_rating')
->when($minRating > 0, function ($query) use($minRating)
{
$query->havingRaw('AVG(review_ratings.rating) >= ?', [$minRating]);
})

Laravel leftJoin only last record of right table

I am new to laravel.
I have two tables.
1) products
2) prices
-----------------------------
- products -
-----------------------------
- id_product | int (p_key) -
- name | varchar -
-----------------------------
-------------------------
- prices -
-----------------------------
- id_price | int (p_key) -
- id_product | int -
- price | int -
-----------------------------
the products table holds data about products like id, name,...
the price changes are stored in prices table where the last record is the newest price that should be displayed to users.
now I want to search through products and get the last price of each product from prices table. this is my query:
$result = DB::table('products')->leftJoin('prices', function($join) {
$join->on('products.id_product', '=', 'prices.id_product');
})->whereRaw(MY_SEARCH_FILTERS);
the above code is wrong because if a product has 4 records in prices table, then it will be repeated 4 times in $result, but only 1 record with the last price should be displayed.
Here we have 2 tables users and answers where users is left table and answers is right table which has user answers.
We wanted to left join users with answers but the join should be with the latest record or answers table.
$query = Users::select('users.id', 'users.user_name','answers.created_at as last_activity_date')
->leftJoin('answers', function($query)
{
$query->on('users.id','=','answers.user_id')
->whereRaw('answers.id IN (select MAX(a2.id) from answers as a2 join users as u2 on u2.id = a2.user_id group by u2.id)');
})
->where('users.role_type_id', Users::STUDENT_ROLE_TYPE)->get();
you can make make it easy by using Laravel Elquent:
class Product extends Model
{
public function lastPrice()
{
// optional: change id_price to created_at by add created_at to prices table
return $this->hasOne(Price::class)->orderBy('id_price', 'DESC');
}
}
now in
public function getProducts(){
$MY_SEARCH_FILTERS=....;
// get all products with last price
$products=Product::with('lastPrice')->whereRaw(MY_SEARCH_FILTERS)->get()
return $products
}
Here we have 2 tables 'articles' and 'comments' where articles is left table and comments is right table which has article's comments.
We wanted to left join articles with comments but the join should be with the latest record from comments table.
$query = Article::select('articles.*', 'comments.comment as article_comment')
->leftJoin('comments', function($query) {
$query->on('comments.article_id','=','articles.id')
->whereRaw('comments.id IN (select MAX(a2.id) from comments as a2 join articles as u2 on u2.id = a2.article_id group by u2.id)');
})
->get();
i found this solution from here https://laravelcode.com/post/how-to-get-last-record-from-leftjoin-table-in-laravel
You need to add two things in here,
1) orderBy descending on prices table.
2) first clause in the DB::table function (It will fetch only 1
record, that will be the latest price).
The solution :
$result = DB::table('products')
->leftJoin('prices',function($join)
{
$join->on('products.id_product', '=', 'prices.id_product')
})->whereRaw(MY_SEARCH_FILTERS)
->orderBy('prices.id_price','desc')
->first();
You can also use (Laravel 5.1) :
$result = DB::table('products')
->leftJoin('products.id','=','prices.id_product')
->whereRaw(MY_SEARCH_FILTERS)
->orderBy('prices.id_price','desc')
->first();

Categories