I have two tables (Table1, Table2).
I want to print the sum of the records whose properties match Table1 in Table2 while listing the Table1 table.
My two tables contain very large records, performance is important to me.
// Model -> relationships
public function cars()
{
return $this->hasMany('App\Models\Table2', 'list_id', 'list_id');
}
// Controller
$table1 = Table1::with('cars' => function($query){
$query->where('table2.color','=', 'table1.color')
$query->where('table2.year','=', 'table1.year')
}])
->get();
I'm adding the sample database pictures:
Thank you.
First, add below use statement to the top of your controller:
use DB;
Now, If you only want to get the records amount, you can do this:
$amount = DB::table('table1')
->join('table2', function($join){
$join->on('table1.color', '=', 'table2.color');
$join->on('table1.year', '=', 'table2.year');
})->count();
But if you want to get the list of the table1 records, you can change the query a bit like below:
$records = DB::table('table1')
->select('table1.*')
->join('table2', function($join){
$join->on('table1.color', '=', 'table2.color');
$join->on('table1.year', '=', 'table2.year');
})->count();
Please follow Laravel's official guide on this topic:
https://laravel.com/docs/8.x/queries#advanced-join-clauses
Use join to merge the two tables read more about join here https://www.w3schools.com/sql/sql_join.asp
Related
I am trying to turn my raw sql into laravel query builder and I encounter difficulty on how to join multiple tables using with many attributes match.
In this case, I want to join the table jr_h and jr_d with three attributes match (book,p_seq and staff_code) rather than one (book).
Raw sql:
$sql = "select from_time,to_time,t.staff_code,s.name_t as staff_name,t.book,t.p_code,t.p_seq,p.hrs1,s.img_file,
t.hrs_work,p.sharing_cnt as hrs_work, t.hrs_ot as hrs_ot from jr_d as t
inner join jr_h as p on(t.book=p.book and t.p_seq=p.p_seq and t.staff_code=p.staff_code)
inner join astaff as s on(t.staff_code=s.staff_code) ";
Laravel query builder:
$jr_d = DB::table('jr_d')
->join('jr_h', 'jr_d.book', '=', 'jr_h.book')
->join('astaff', 'jr_d.staff_code', '=', 'astaff.staff_code')
->select('jr_h.*','jr_d.*','astaff.*','astaff.name_t as staff_name')
->where('jr_d.ref_group','=','E')
->get();
and also want to know if there is a way to make the query faster since it has a lot of data in the tables.
Laravel joins with multiple conditions:
$results = DB::table('jr_d')
->select('jr_h.*','jr_d.*','astaff.*','astaff.name_t as staff_name')
->join('jr_h', 'jr_d.book', '=', 'jr_h.book')
->join('jr_h as p', function($query){
$query->on('t.book','=', p.book');
$query->on('t.p_seq','=', 'p.p_seq');
$query->on('t.staff_code', '=', 'p.staff_code');
})
->where('jr_d.ref_group','=','E')
->get();
`
Try this:
// ...
->join('jr_h p', function($join) {
$join->on('t.book', '=', 'p.book');
$join->on('t.p_seq', '=', 'p.p_seq');
// ... more conditions
});
Try this.
$jr_d = DB::table('jr_d')
->join('jr_h', 'jr_d.book', '=', 'jr_h.book')
->join('astaff', 'jr_d.staff_code', '=', 'astaff.staff_code')
->select('*','astaff.name_t as staff_name')
->where('jr_d.ref_group','=','E')
->get();
I have the following query:
Ratings::join('users', 'movieratings.rated_by', '=', 'users.usr_id')
->where('rated_on', $movieId)
->orderBy('rated_at', 'desc')
->select('comment', 'rating', 'rated_as', 'rated_at', 'username')
->paginate(20);
This will get all the feedback ratings for a specific movie.
But I have another table which contains the total good and bad ratings for a specific movie movie, the only problem is that I cant get it to work to query that table as well at the same time.
If I do another query I would simply write: Movie::where('movie_id', $movieId)->select('total_good_ratings', 'total_bad_ratings')->get(); this would output eg "22, 15" but is it possible to only fetch two columns from a specific row then do a inner join between two tables and paginate the result?
thanks
You can do a leftJoin with the table that contains the good and bad ratings, where the join condition will be the id of the movie.
Ratings::join('users', 'movieratings.rated_by', '=', 'users.usr_id')
->leftJoin('movie', 'movie.id', '=', 'movieratings.rated_on')
->where('rated_on', $movieId)
->orderBy('rated_at', 'desc')
->select('comment', 'rating', 'rated_as', 'rated_at', 'username', 'total_good_ratings', 'total_bad_ratings')
->paginate(20);
I think you can try this:
Ratings::leftJoin('users', 'users.usr_id', '=', 'movieratings.rated_by')
->leftJoin('movie', 'movie.id', '=', 'movieratings.rated_on')
->where('movieratings.rated_on', $movieId)
->orderBy('movie.rated_at', 'desc')
->select('movieratings.comment', 'movieratings.rating', 'movieratings.rated_as', 'movie.rated_at', 'users.username', 'movieratings.total_good_ratings', 'movieratings.total_bad_ratings')
->paginate(20);
Hope this help for you !!!
In case this may be of help:
Assuming:
class Rating extends Model {
public users() {
$this->belongsTo(User::class, 'usr_id');
}
public movie() {
$this->belongsTo(Movie::class, 'rated_on'); //Name looks odd, it should be movie_id if you are following standard conventions
}
}
Then you can lazy/eaher load them:
$ratings = Ratings::with([ "movie" => function ($query) {
$q->select('total_good_ratings', 'total_bad_ratings');
}])->where('rated_on', $movieId)
->orderBy('rated_at', 'desc')
->select('comment', 'rating', 'rated_as', 'rated_at', 'username',"rated_on")
->paginate(20);
You can get the movie info via $ratings[X]->movie->total_good_ratings (in a loop that would be $rating->movie->total_good_ratings
A bit of critique though:
total_good_ratings looks like it's a derived attribute so it should not have been stored in the first place. It's appears to be a count of the good ratings.
You should use the standard conventions when naming columns and tables e.g. a foreign key is usually called <foreign table name in singular>_<foreign field name> example user_id or movie_id .
I'm new to laravel and I have some issues with the query builder.
The query I would like to build is this one:
SELECT SUM(transactions.amount)
FROM transactions
JOIN categories
ON transactions.category_id == categories.id
WHERE categories.kind == "1"
I tried building this but it isn't working and I can't figure out where I am wrong.
$purchases = DB::table('transactions')->sum('transactions.amount')
->join('categories', 'transactions.category_id', '=', 'categories.id')
->where('categories.kind', '=', 1)
->select('transactions.amount')
->get();
I would like to get all the transactions that have the attribute "kind" equal to 1 and save it in a variable.
Here's the db structure:
transactions(id, name, amount, category_id)
categories(id, name, kind)
You don't need to use select() or get() when using the aggregate method as sum:
$purchases = DB::table('transactions')
->join('categories', 'transactions.category_id', '=', 'categories.id')
->where('categories.kind', '=', 1)
->sum('transactions.amount');
Read more: http://laravel.com/docs/5.0/queries#aggregates
If one needs to select SUM of a column along with a normal selection of other columns, you can sum select that column using DB::raw method:
DB::table('table_name')
->select('column_str_1', 'column_str_2', DB::raw('SUM(column_int_1) AS sum_of_1'))
->get();
You can get some of any column in Laravel query builder/Eloquent as below.
$data=Model::where('user_id','=',$id)->sum('movement');
return $data;
You may add any condition to your record.
Thanks
MyModel::where('user_id', $_some_id)->sum('amount')
I have 2 tables: users and articles. To fetch all columns from the articles table and only user_name column from the users table, I use this code:
$articles = Article::join('users', 'articles.user_id', '=', 'users.user_id')
->get(array('articles.*', 'users.user_name'));
and it works fine, but when I use paginate() method like this:
$articles = Article::join('users', 'articles.user_id', '=', 'users.user_id')
->paginate(10);
it fetches all columns from both tables, which I don't want. My question is: How can I select columns that will be returned in the result if I use paginate() method in Laravel framework?
The select function does this.
$articles = Article::join('users', 'articles.user_id', '=', users.user_id')
->select('articles.*', 'users.user_name')
->paginate(10);
I am attempting to do the equivalent of this:
select p.id, p.title, b.brand,
(select big from images where images.product_id = p.id order by id asc limit 1) as image
from products p
inner join brands b on b.id = p.brand_id
Here is where I am at now, but it of course doesn't work:
public function getProducts($brand)
{
// the fields we want back
$fields = array('p.id', 'p.title', 'p.msrp', 'b.brand', 'p.image');
// if logged in add more fields
if(Auth::check())
{
array_push($fields, 'p.price_dealer');
}
$products = DB::table('products as p')
->join('brands as b', 'b.id', '=', 'p.brand_id')
->select(DB::raw('(select big from images i order by id asc limit 1) AS image'), 'i.id', '=', 'p.id')
->where('b.active', '=', 1)
->where('p.display', '=', 1)
->where('b.brand', '=', $brand)
->select($fields)
->get();
return Response::json(array('products' => $products));
}
I don't really see anything in the docs on how to do this, and I can't seem to piece it together from other posts.
In "regular" SQL, the subquery is treated AS a column, but I am not sure how to string that together here. Thanks for any help on this.
I strongly recommend you to use Eloquent, instead of pure SQL. It's one of the most beautful things in Laravel. Two models and relations and it's done! If you need to use pure SQL like that, put it all in DB::raw. It's easier, simpler and (ironically) less messy!
With the models, you could use relations between the two tables (represented by the models itself) and say (so far I understood) that Brands belongs to Products, and Images belongs to Product. Take a look at Eloquent's documentation on Laravel. Probably will be more clearly.
Once the relations are done, you can only say that you wanna get
$product = Product::where(function ($query) use ($brand){
$brand_id = Brand::where('brand', '=', $brand)->first()->id;
$query->where('brand_id', '=', $brand_id);
})
->image()
->get();
That and a better look at Eloquent's documentation should help you to do the job.
P.S.: I didn't test the code before send it and wrote it by head, but i think it works.