I need to convert that query in laravel Query - mysql

SELECT *
FROM `events`
WHERE (`customer_bookable` = 1 and template = 1 )
OR (`customer_bookable` = 0 and template = 0 )
and (`start_date_time` BETWEEN '2017-09-01 00:00:00' and '2017-09-21 00:00:00')
And (profile_id = 10)
and (event_live_status = 1)
and (class != 0)
and (privacy_status = 1)

Do you need help with the 'or' part? You can use closures where you would use parenthesis in SQL:
...
->where( function ($query) {
$query->where('customer_bookable',1)
->where('template',1);
})->orWhere( function ($query) {
$query->where('customer_bookable',0)
->where('template',0);
})
...

Your query may look like this,
$events = DB::('events')
->where( function ($query) {
$query->where('customer_bookable',1)
->where('template',1)
->orWhere('customer_bookable',0)
->orWhere('template',0);
})
->where( function ($query) {
$query->whereBetween('start_date_time',['2017-09-01 00:00:00' and '2017-09-21 00:00:00'])
->where('profile_id',10)
->where('event_live_status',1)
->where('class','!=',0)
->where('privacy_status',1);
});

Related

Laravel subquery in from clause

I need to use subquery in from clause but i can not find such thing in Laravel docs
Laravel version 5.4
$sub = Chat::join("chats as _chats", function ($query) {
$query->on('chats.room_id', "=", "_chats.room_id")
->on('chats.user_type', "<>", "_chats.user_type")
->on('chats.created_at', "=", DB::raw("(SELECT MIN(created_at) FROM chats WHERE created_at > '_chats.created_at')"));
})
->selectRaw('TIMESTAMPDIFF(MINUTE, _chats.created_at, chats.created_at) as res')
->where('chats.user_type', 'pharmacy_consultant')
->where('chats.user_id', 26)
->toSql();
dd(
DB::connection('mysql2')
->table(DB::raw("({$sub}) as sub"))
->select('res')
->get()
);
(2/2) QueryException SQLSTATE[HY000]: General error: 2031
(SQL: select `res` from (select TIMESTAMPDIFF(MINUTE, _chats.created_at, chats.created_at) as res
from `chats` inner join `chats` as `_chats` on `chats`.`room_id` = `_chats`.`room_id` and `chats`.`user_type` <> `_chats`.`user_type` and `chats`.`created_at` =
(SELECT MIN(created_at) FROM chats WHERE created_at > _chats.created_at) where `chats`.`user_type` = ? and `chats`.`user_id` = ?) as sub)
Try passing the builder instance instead of the raw query.
// $sub = Query Builder instance
$sub = Chat::join("chats as _chats", function ($query) {
$query->on('chats.room_id', "=", "_chats.room_id")
->on('chats.user_type', "<>", "_chats.user_type")
->on('chats.created_at', "=", DB::raw("(SELECT MIN(created_at) FROM chats WHERE created_at > '_chats.created_at')"));
})
->selectRaw('TIMESTAMPDIFF(MINUTE, _chats.created_at, chats.created_at) as res')
->where('chats.user_type', 'pharmacy_consultant')
->where('chats.user_id', 26);
// ->toSql();
DB::connection('mysql2')
->table($sub, "sub")
->select('res')
->get()
Since you're not doing anything else than a select in your final query, why not just do that in the first query instead?
$results = Chat::join("chats as _chats", function ($query) {
$query->on('chats.room_id', "=", "_chats.room_id")
->on('chats.user_type', "<>", "_chats.user_type")
->on('chats.created_at', "=", DB::raw("(SELECT MIN(created_at) FROM chats WHERE created_at > '_chats.created_at')"));
})
->selectRaw('TIMESTAMPDIFF(MINUTE, _chats.created_at, chats.created_at) as res')
->where('chats.user_type', 'pharmacy_consultant')
->where('chats.user_id', 26)
->select('res')
->get();
Make it fit to your needs:
...
->addSelect([res' => ChartModel::select('//whatever')
->whereColumn('//sub-query column', 'parent-table.field')
->whereColumn('//and whatever')
->latest()
->take(1)
)]
...

Adding OR statements to Eloquent Queries

I need a little help regarding the syntax of Eloquent. I want to add more where clauses but can't get the OR working. I read https://laravel.com/docs/7.x/queries#where-clauses but my statement fails.
Works:
$events = DB::table('events')->select('id','resourceId','title','start','end')
->whereDate('start', '>=', $start)->whereDate('end', '<=', $end)->get();
Does not work:
$events = DB::table('events')->select('id','resourceId','title','start','end')
->whereDate('start', '>=', $start)->whereDate('end', '<=', $end)
->orWhere(function($query) {
$query->whereDate('start', '<=', $start)
->whereDate('end', '>=', $end);
})
->get();
Is orWhere not supposed to work with whereDate?
First; while using closures you need to pass arguments with use. You may or two main conditions and in their nested conditions both sub-conditions will be anded.
public function index()
{
DB::table('events')
->select('id', 'resourceId', 'title', 'start', 'end')
->where(function ($query) use ($start, $end) {
$query->whereDate('start', '>=', $start)->whereDate('end', '<=', $end);
})
->orWhere(function ($query) use ($start, $end) {
$query->whereDate('start', '<=', $start)->whereDate('end', '>=', $end);
})
->get();
}
This function will print (don't mind about the dates, just example)
SELECT `id`, `resourceId`, `title`, `start`, `end`
FROM `events`
WHERE (date(`start`) >= '2020-06-15' and date(`end`) <= '2020-06-16')
or (date(`start`) <= '2020-06-15' and date(`end`) >= '2020-06-16')

Why is DB::raw variable being amended from a string to an integer in Laravel 5.7

I have the following part of a larger elequent query, which all works when I'm not injecting a variable into DB::raw.
$tests->join('test_categories', function ($join) use($request) {
$join->on('test_categories.id', '=', DB::raw('(select category_id
from test_category
join test_categories on test_category.category_id = test_categories.id
where test_category.test_id = tests.id
and test_categories.name = ?
limit 1)', ['Cars']
));
});
But when the SQL executes it amends the '?' to 4, as in:
and test_categories.name = 4
Rather than being the expected:
and test_categories.name = 'Cars'
Any help would be appreciated.
UPDATED
I also tried the following before:
$tests->join('test_categories', function ($join) use ($category) {
$join->on('test_categories.id', '=', DB::raw("(select category_id
from test_category
join test_categories on test_category.category_id = test_categories.id
where test_category.test_id = tests.id
and test_categories.name = :category
limit 1)",array('category' => $category)));
});
But in the query, this just outputs the following:
and test_categories.name = :category
This comes with a "SQLSTATE[HY093]: Invalid parameter number: mixed named and positional parameters" error.
Still the same issue.
And another variation which tries the same technique with the $join->on function.
$tests->join('test_categories', function ($join) use ($category) {
$join->on('test_categories.id', '=', DB::raw("(select category_id
from test_category
join test_categories on test_category.category_id = test_categories.id
where test_category.test_id = tests.id
and test_categories.name = :category
limit 1)"),array('category' => $category));
});
This results in an ErrorException (E_NOTICE) Array to string conversion:
protected function compileWheresToArray($query)
{
return collect($query->wheres)->map(function ($where) use ($query) {
return $where['boolean'].' '.$this->{"where{$where['type']}"}($query, $where);
})->all();
}
Based on this link you could use
$results = DB::select( DB::raw("SELECT * FROM some_table WHERE some_col = :somevariable"), array(
'somevariable' => $someVariable,
));
Try replacing :category with ".$category.".
Not sure if it's a good practice to do it this way but it should work.
$tests->join('test_categories', function ($join) use ($category) {
$join->on('test_categories.id', '=', DB::raw("(select category_id
from test_category
join test_categories on test_category.category_id = test_categories.id
where test_category.test_id = tests.id
and test_categories.name = ".$category."
limit 1)"));
});

MySQL date in between month and year

How to query date month and year between from_date and to_date?
What I tired:
$posts = my_table::whereYear('from_date', '>=', $year)
->whereMonth('from_date', '>=', $month)
->whereYear('to_date', '<=', $year)
->whereMonth('to_date', '<=', $month)
->get();
Query I want to execute:
SELECT * FROM my_table
WHERE (MONTH(from_date)>=2 AND (Year(from_date)>=2019)
AND (MONTH(to_date)=<4 AND (Year(to_date)=<2019)
I think this is what you might be looking for:
$posts = my_table::whereRaw("(MONTH('from_date') > 2 AND YEAR('from_date') >= 2019)")
->whereRaw("(MONTH('to_date') < 4 AND YEAR('to_date') <= 2019)")
->get();
Here's an example.
You can use the eloquent method too.
$result = my_table::where(function($query){
$query->where(DB::raw('MONTH(from_date)'), '>=' , 2)
->where(DB::raw('Year(from_date)'), '>=' , 2019);
})
->where(function($query){
$query->where(DB::raw('MONTH(to_date)'), '<=' , 4)
->where(DB::raw('YEAR(to_date)'), '<=' , 2019);
})
->get();
you may also do it in this way.
return Post::whereRaw("STR_TO_DATE('from_date', '%M%Y') > STR_TO_DATE('022019', '%M%Y')")
->whereRaw("STR_TO_DATE('from_date', '%M%Y') < STR_TO_DATE('042019', '%M%Y')")
->get();

Doctrine - QueryBuilder: verify if query returns results (Count)

I have a query which in two stages:
public function findOtherRosters($user){
$q2 = $this->createQueryBuilder('r')
->leftJoin('r.members', 'm')
->addSelect('m')
->where('m.user = :user')
->setParameter('user', $user);
$qb = $this->createQueryBuilder('ro');
$qb
->where('ro not IN (:rosters)')
->setParameter('rosters', $q2->getQuery()->getResult())
;
return $qb->getQuery()
->getResult();
I need to check if the first query ($qb) returns results. If result I run a query, if not another query. At the moment my code is as followed:
public function findOtherRosters($user){
$q2 = $this->createQueryBuilder('r')
->leftJoin('r.members', 'm')
->addSelect('m')
->where('m.user = :user')
->setParameter('user', $user);
if ( is_null($q2) ){ // the issue is here
$qb = $this->createQueryBuilder('ro');
$qb
->where ('ro not IN (:rosters)')
->setParameter('rosters', $q2->getQuery()->getResult())
;
} else {
$qb = $this->createQueryBuilder('ro');
}
return $qb->getQuery()
->getResult();
}
The issue is with the is_null ; I need to check if the first query returns any lines not if is null.
Any ideas?
I might have misunderstood your intention here but shouldn't you getResult() first in order to check that?
Somthing like this?
public function findOtherRosters($user){
$q2 = $this->createQueryBuilder('r')
->leftJoin('r.members', 'm')
->addSelect('m')
->where('m.user = :user')
->setParameter('user', $user);
$q2Result = $q2->getQuery()->getResult(); // <<---- THIS
if ( count($q2Result) ){ // the issue is here <<--- THIS
$qb = $this->createQueryBuilder('ro');
$qb
->where ('ro not IN (:rosters)')
->setParameter('rosters', $q2Result) // <<---- THIS
;
} else {
$qb = $this->createQueryBuilder('ro');
}
return $qb->getQuery()
->getResult();
}