Can anyone help me out to convert this SQL to query builder!
SELECT topwords.*,
mw.word AS my_word
FROM topwords
LEFT JOIN (SELECT DISTINCT words.word
FROM definition_word
JOIN words
ON words.id = definition_word.word_id
WHERE definition_word.user_id = $user) AS mw
ON topwords.word = mw.word
I have a problem with how to use a subquery in leftjoin!
I tried something like this but it has error!
See error as image
DB::table('topwords')
->leftJoin(DB::raw("SELECT DISTINCT
words.word
FROM definition_word
JOIN words ON words.id = definition_word.word_id
WHERE definition_word.user_id = $user as mw"),"topwords.word", "=", "mw.word" )
->select(
"topwords.*",
"mw.word AS my_word"
)->orderBy('id','desc')->paginate(15);
you can use Join Sub query official document subquery-joins
$mw = DB::table('words')
->select('DISTINCT words.word')
->join('definition_word', function($join) use ($user)
{
$join->on('wordss.id', '=', 'definition_word.word_id')
->where('definition_word.user_id', $user);
});
$topwords = DB::table('topwords')
->joinSub($mw, 'mw',function ($join) {
$join->on('topwords.word', '=', 'mw.word');
})
->select('topwords.*','mw.word AS my_word')
->orderBy('id','desc')
->paginate(15);
You have this error because of paginate and aggregation
Try to make custom pagination, using LengthAwarePaginator
Here is example: Laracast
So you need to make something like this:
$query = DB::table('topwords')
->leftJoin(DB::raw("SELECT DISTINCT
words.word
FROM definition_word
JOIN words ON words.id = definition_word.word_id
WHERE definition_word.user_id = $user as mw"),"topwords.word", "=", "mw.word" )
->select(
"topwords.*",
"mw.word AS my_word"
);
$paginator = new LengthAwarePaginator($query->get(), $query->count(), $request->input('per_page', 15), $request->input('page', 1));
And then you can use it in the collection
I am using Laravel Framework 6.16.0 and I am having the following eloquent query:
$symbols = Company::select('*')
->leftJoin('prices', 'companies.id', '=', 'prices.companies_id')
->whereNotIn('companies.id', Price::select('companies_id')->get()->toArray())
->whereNotIn('companies.symbol', APIFound::select('generic_identifier')->get()->toArray())
->limit(1000)
->get();
This should represent the following sql query:
SELECT
*
FROM
companies c
LEFT JOIN prices p ON
c.id = p.companies_id
WHERE
c.id NOT IN(
SELECT
p.companies_id
FROM
prices p
) OR c.symbol NOT IN(
SELECT
f.generic_identifier
FROM
a_p_i_founds f
)
However, I get an and between my whereNotIn() function. How to get an or()?
I appreciate your replies!
you can use (where) with function:
$symbols = Company::select('*')
->leftJoin('prices', 'companies.id', '=', 'prices.companies_id')
->where(function ($query)
{
$query->whereNotIn('companies.id', Price::select('companies_id')->get()->toArray());
})
->orWhere(function ($query){
$query->whereNotIn('companies.symbol', APIFound::select('generic_identifier')->get()->toArray());
})
->limit(1000)
->get();
I upgraded Laravel to version 7, and when I do a query like this:
$users = User::where('name', '=', 'John')
->where(function ($query) {
$query->where('votes', '>', 100)
->orWhereNull('title');
})
->get();
it doesn't work as expected, and I got this error [SQL Server] Must specify table to select from
because the SQL should be like this:
select * from users where name = 'John' and (votes > 100 or title is null)
but when I debug the returned query it shows like this:
select * from users where name = 'John' and (select * votes > 100 or title is null) is null
The above query it just an example of my complex query, and I have a lot like this query in all of my project so I don't need a replacement, I just need to know how to fix it as it worked fine before upgrading
You can use whereRaw for the alternative method, for example
$users = Table::whereRaw(" name=? AND (votes=? OR title=?)", array(?,?,?))
$users = User::where('name', '=', 'John')
->where(function ($query) {
$query->from('users')
->where('votes', '>', 100)
->orWhereNull('title');
})
->get();
I have the following query was built by Laravel:
$res = Announcement::whereExists(function ($query) {
$query->select(DB::raw(1))
->from('announcement_category')->join('user_category', 'user_category.category_id', '=', 'announcement_category.category_id')
->where('user_category.user_id', '=', 1)
->where('announcement_category.announcement_id', '=', 'announcements.id');
});
dd($res->get());
The code above gives me empty collection: dd($res->get());.
The plain SQL code of this query is:
select * from `announcements` where exists (select 1 from
`announcement_category` inner join `user_category` on
`user_category`.`category_id` = `announcement_category`.`category_id` where `user_category`.`user_id` = 1
and `announcement_category`.`announcement_id` = announcements.id)
and `announcements`.`deleted_at` is null
If execute this directly in MySQL, I get two result rows.
But why dd($res->get()); retuns me empty?
I don't think there is a whereExists in eloquent model... try this:
$res = DB::table('announcement')->whereExists(function ($query) {
$query->select(DB::raw(1))
->from('announcement_category')->join('user_category', 'user_category.category_id', '=', 'announcement_category.category_id')
->where('user_category.user_id', '=', 1)
->where('announcement_category.announcement_id', '=', 'announcements.id');
})->get();
I'm trying to add a condition using a JOIN query with Laravel Query Builder.
<?php
$results = DB::select('
SELECT DISTINCT
*
FROM
rooms
LEFT JOIN bookings
ON rooms.id = bookings.room_type_id
AND ( bookings.arrival between ? and ?
OR bookings.departure between ? and ? )
WHERE
bookings.room_type_id IS NULL
LIMIT 20',
array('2012-05-01', '2012-05-10', '2012-05-01', '2012-05-10')
);
I know I can use Raw Expressions but then there will be SQL injection points. I've tried the following with Query Builder but the generated query (and obviously, query results) aren't what I intended:
$results = DB::table('rooms')
->distinct()
->leftJoin('bookings', function ($join) {
$join->on('rooms.id', '=', 'bookings.room_type_id');
})
->whereBetween('arrival', array('2012-05-01', '2012-05-10'))
->whereBetween('departure', array('2012-05-01', '2012-05-10'))
->where('bookings.room_type_id', '=', null)
->get();
This is the generated query by Laravel:
select distinct * from `room_type_info`
left join `bookings`
on `room_type_info`.`id` = `bookings`.`room_type_id`
where `arrival` between ? and ?
and `departure` between ? and ?
and `bookings`.`room_type_id` is null
As you can see, the query output doesn't have the structure (especially under JOIN scope). Is it possible to add additional conditions under the JOIN?
How can I build the same query using Laravel's Query Builder (if possible) Is it better to use Eloquent, or should stay with DB::select?
$results = DB::table('rooms')
->distinct()
->leftJoin('bookings', function($join)
{
$join->on('rooms.id', '=', 'bookings.room_type_id');
$join->on('arrival','>=',DB::raw("'2012-05-01'"));
$join->on('arrival','<=',DB::raw("'2012-05-10'"));
$join->on('departure','>=',DB::raw("'2012-05-01'"));
$join->on('departure','<=',DB::raw("'2012-05-10'"));
})
->where('bookings.room_type_id', '=', NULL)
->get();
Not quite sure if the between clause can be added to the join in laravel.
Notes:
DB::raw() instructs Laravel not to put back quotes.
By passing a closure to join methods you can add more join conditions to it, on() will add AND condition and orOn() will add OR condition.
If you have some params, you can do this.
$results = DB::table('rooms')
->distinct()
->leftJoin('bookings', function($join) use ($param1, $param2)
{
$join->on('rooms.id', '=', 'bookings.room_type_id');
$join->on('arrival','=',DB::raw("'".$param1."'"));
$join->on('arrival','=',DB::raw("'".$param2."'"));
})
->where('bookings.room_type_id', '=', NULL)
->get();
and then return your query
return $results;
You can replicate those brackets in the left join:
LEFT JOIN bookings
ON rooms.id = bookings.room_type_id
AND ( bookings.arrival between ? and ?
OR bookings.departure between ? and ? )
is
->leftJoin('bookings', function($join){
$join->on('rooms.id', '=', 'bookings.room_type_id');
$join->on(DB::raw('( bookings.arrival between ? and ? OR bookings.departure between ? and ? )'), DB::raw(''), DB::raw(''));
})
You'll then have to set the bindings later using "setBindings" as described in this SO post:
How to bind parameters to a raw DB query in Laravel that's used on a model?
It's not pretty but it works.
The sql query sample like this
LEFT JOIN bookings
ON rooms.id = bookings.room_type_id
AND (bookings.arrival = ?
OR bookings.departure = ?)
Laravel join with multiple conditions
->leftJoin('bookings', function($join) use ($param1, $param2) {
$join->on('rooms.id', '=', 'bookings.room_type_id');
$join->on(function($query) use ($param1, $param2) {
$query->on('bookings.arrival', '=', $param1);
$query->orOn('departure', '=',$param2);
});
})
I am using laravel5.2 and we can add joins with different options, you can modify as per your requirement.
Option 1:
DB::table('users')
->join('contacts', function ($join) {
$join->on('users.id', '=', 'contacts.user_id')->orOn(...);//you add more joins here
})// and you add more joins here
->get();
Option 2:
$users = DB::table('users')
->join('contacts', 'users.id', '=', 'contacts.user_id')
->join('orders', 'users.id', '=', 'orders.user_id')// you may add more joins
->select('users.*', 'contacts.phone', 'orders.price')
->get();
option 3:
$users = DB::table('users')
->leftJoin('posts', 'users.id', '=', 'posts.user_id')
->leftJoin('...', '...', '...', '...')// you may add more joins
->get();
For conditional params we can use where,
$results = DB::table('rooms')
->distinct()
->leftJoin('bookings', function($join) use ($param)
{
$join->on('rooms.id', '=', 'bookings.room_type_id')
->where('arrival','=', $param);
})
->where('bookings.room_type_id', '=', NULL)
->get();
There's a difference between the raw queries and standard selects (between the DB::raw and DB::select methods).
You can do what you want using a DB::select and simply dropping in the ? placeholder much like you do with prepared statements (it's actually what it's doing).
A small example:
$results = DB::select('SELECT * FROM user WHERE username=?', ['jason']);
The second parameter is an array of values that will be used to replace the placeholders in the query from left to right.
My five cents for scheme LEFT JOIN ON (.. or ..) and (.. or ..) and ..
->join('checks','checks.id','check_id')
->leftJoin('schema_risks', function (JoinClause $join) use($order_type_id, $check_group_id, $filial_id){
$join->on(function($join){
$join->on('schema_risks.check_method_id','=', 'check_id')
->orWhereNull('schema_risks.check_method_id')
;
})
->on(function($join) use ($order_type_id) {
$join->where('schema_risks.order_type_id', $order_type_id)
->orWhereNull('schema_risks.order_type_id')
;
})
->on(function($join) use ($check_group_id) {
$join->where('schema_risks.check_group_id', $check_group_id)
->orWhereNull('schema_risks.check_group_id')
;
})
->on(function($join) use($filial_id){
$join->whereNull('schema_risks.filial_id');
if ($filial_id){
$join->orWhere('schema_risks.filial_id', $filial_id);
}
})
->on(function($join){
$join->whereNull('schema_risks.check_risk_level_id')
->orWhere('schema_risks.check_risk_level_id', '>' , CheckRiskLevel::CRL_NORMALLLY );
})
;
})