I need to select several rows that respect these conditions:
date >= today
keyword present in fields 1, 2 or 3
i guess the SQL statement for this should be:
SELECT * FROM `events` WHERE date >= '2010-09-12' AND (field1 LIKE '%keyword%' OR field2 LIKE '%keyword%' OR field3 LIKE '%keyword%')
I am trying to write this using codeigniter's active records, but the the LIKE condition seems to override the date one.
$this->db->select('*');
$this->db->join('venues', 'events.venue = venue_id');
//first condition: date >= today
$this->db->where('date >=', date('Y-m-d'));
if ($keyword)
//if keyword is present, add this condition as well
{
$this->db->like('events.description', $keyword);
$this->db->or_like('band', $keyword);
$this->db->or_like('venues.venue', $keyword);
}
$this->db->order_by('date', 'ASC');
$this->db->order_by('events.priority', 'DESC');
$Q = $this->db->get('events');
I probably need to insert the LIKE statement inside a parentesis, but don't know how to do it.
I think you have to write the 'like'-part of your query this way:
$this->db->select('*');
$this->db->join('venues', 'events.venue = venue_id');
if ($keyword)
//if keyword is present, add this condition as well
{
$where = "( events.description LIKE '$keyword' OR band LIKE '$keyword' OR venues.venue LIKE '$keyword')";
$this->db->where($where);
}
//first condition: date >= today
$this->db->where('date >=', date('Y-m-d'));
$this->db->order_by('date', 'ASC');
$this->db->order_by('events.priority', 'DESC');
$Linkearray = array('page_content' => $search, 'page_title' => $search);
$this->db->like($Linkearray);
$this->db->where('page_online',1);
$this->db->where('page_site',$page_site);
// WHERE page_content LIKE '% my Text%'
// AND page_title LIKE '% my page title %'
// AND page_online = '1' and page_site ='29'
$array = array('title' => $match, 'page1' => $match, 'page2' => $match);
$this->db->like($array);
// WHERE title LIKE '%match%' AND page1 LIKE '%match%' AND page2 LIKE '%match%'
Related
My Expected query is
select count(*) as aggregate from `books`
where (`books`.`is_deleted` = 0)
and `category_id` = '61'
and (`title` like '%問いかけの作法 チームの魅力と才能を引き出す技術%' or `title` like '%問イカケノ作法 チームノ魅力ト才能ヲ引キ出ス技術%' or `title` like '%問いかけの作法 ちーむの魅力と才能を引き出す技術%');
I have written my conditions like below ways
$queryCondition = $this::where(['books.is_deleted' => false]);
if( isset($queryString['category']) ){
$queryCondition->where('category_id',$queryString['category']);
}
if( isset($queryString['searchKey']) ){
$search = mb_convert_kana($queryString['searchKey'],"rns");
$kana = mb_convert_kana($search,"KVC");
$katakana = mb_convert_kana($search,"KVc");
$queryCondition->where('title','like','%'.$search.'%')
->orWhere('title','like','%'.$kana.'%')
->orWhere('title','like','%'.$katakana.'%')
;
}
I'm getting the output query like below
select count(*) as aggregate from `books`
where (`books`.`is_deleted` = 0)
and `category_id` = '61'
and `title` like '%問いかけの作法 チームの魅力と才能を引き出す技術%' or `title` like '%問イカケノ作法 チームノ魅力ト才能ヲ引キ出ス技術%' or `title` like '%問いかけの作法 ちーむの魅力と才能を引き出す技術%';
Without the () in last condition. How can I fix it ? Without this way has there any other ways to implement nested or in laravel ? Example
$query->where([
'OR' => [
[name LIKE' => '%'.$search.'%'],
[search LIKE' => '%'.$kana.'%'],
[search LIKE' => '%'.$katakana.'%']
]
]);
try this
->where(function ($query) {
$query->where('title','like','%問いかけの作法 チームの魅力と才能を引き出す技術%')
->orWhere('title','like','%問イカケノ作法 チームノ魅力ト才能ヲ引キ出ス技術%')
->orWhere('title','like','%問いかけの作法 ちーむの魅力と才能を引き出す技術%');
})
->get();
The closure will give you the () that you are seeking for.
Laravel documentation 9.x itself asks to add orwhere via above.
You should always group orWhere calls in order to avoid unexpected behavior when global scopes are applied.
From docs:
$users = DB::table('users')
->where('votes', '>', 100)
->orWhere(function($query) {
$query->where('name', 'Abigail')
->where('votes', '>', 50);
})
->get();
which will give you,
select * from users where votes > 100 or (name = 'Abigail' and votes > 50)
You should try whereRaw with raw query instead of orWhere
So, instead of this
->orWhere('title','like','%'.$kana.'%')
->orWhere('title','like','%'.$katakana.'%');
Do this
->whereRaw('title LIKE "%$kana%" OR title LIKE "%$katakana%" ');
From my experience, anytime i use orWhere(), it ignores all other conditions so i prefer to use whereRaw and it works fine for me without any issues
I have a dB query where I would like to groupBy() only when conditions are met without using union because of pagination.
Unfortunately groupBy() seems to only work when called on the entire query outside of the loop.
This was made for dynamic filtering from $filterArr. Depending on the array I need to select from different columns of the table.
When the $key=='pattern' I would need the distinct results from its column.
the query looks something like this
select `col_1`, `col_2`, `col_3`
from `mytable`
where (`color` LIKE ? or `pattern` LIKE ? or `style` LIKE ?)
group by `col_2` //<< i need this only for 'pattern' above and not the entire query
Heres the model:
// $filterArr example
// Array ( [color] => grey [pattern] => stripe )
$query = DB::table('mytable');
$query = $query->select(array('col_1', 'col_2', 'col_3'), DB::raw('count(*) as total'));
$query = $query->where(function($query) use ($filterArr){
$ii = 0;
foreach ($filterArr as $key => $value) {
if ($key=='color'){
$column = 'color';
}else if ($key=='style'){
$column = 'style';
}else if ($key=='pattern'){
$column = 'pattern';
$query = $query->groupBy('col_2'); // << !! does not work
}
if($ii==0){
$query = $query->where($column, 'LIKE', '%'.$value.'%');
}
else{
$query = $query->orWhere($column, 'LIKE', '%'.$value.'%');
}
$ii++;
}
});
$query = $query->orderBy('col_2', 'asc')->simplePaginate(30);
I think you can simplify your code a bit:
$query = DB::table('mytable');
$query = $query->select(array('col_1', 'col_2', 'col_3'), DB::raw('count(*) as total'));
$query = $query->where(
collect($filterArr)
->only(['color','style','pattern'])
->map(function ($value, $key) {
return [ $key, 'like', '%'.$value.'%', 'OR' ];
})->all()
)->when(array_key_exists('pattern', $filterArr), function ($query) {
return $query->groupBy('col_2');
});
$query = $query->orderBy('col_2', 'asc')->simplePaginate(30);
I am using laravel eager loading to load data on the jquery datatables. My code looks like:
$columns = array(
0 => 'company_name',
1 => 'property_name',
2 => 'amenity_review',
3 => 'pricing_review',
4 => 'sqft_offset_review',
5 => 'created_at',
6 => 'last_uploaded_at'
);
$totalData = Property::count();
$limit = $request->input('length');
$start = $request->input('start');
$order = $columns[$request->input('order.0.column')];
$dir = $request->input('order.0.dir');
$query = Property::with(['company','notices']);
$company_search = $request->columns[0]['search']['value'];
if(!empty($company_search)){
$query->whereHas('company', function ($query) use($company_search) {
$query->where('name','like',$company_search.'%');
});
}
$property_search = $request->columns[1]['search']['value'];
if(!empty($property_search)){
$query->where('properties.property_name','like',$property_search.'%');
}
if(!Auth::user()->hasRole('superAdmin')) {
$query->where('company_id',Auth::user()->company_id);
}
$query->orderBy($order,$dir);
if($limit != '-1'){
$records = $query->offset($start)->limit($limit);
}
$records = $query->get();
With this method I received error: Column not found: 1054 Unknown column 'company_name' in 'order clause' .
Next, I tried with following order condition:
if($order == 'company_name'){
$query->orderBy('company.name',$dir);
}else{
$query->orderBy($order,$dir);
}
However, it also returns similar error: Column not found: 1054 Unknown column 'company.name' in 'order clause'
Next, I tried with whereHas condition:
if($order == 'company_name'){
$order = 'name';
$query->whereHas('company', function ($query) use($order,$dir) {
$query->orderBy($order,$dir);
});
}else{
$query->orderBy($order,$dir);
}
But, in this case also, same issue.
For other table, I have handled this type of situation using DB query, however, in this particular case I need the notices as the nested results because I have looped it on the frontend. So, I need to go through eloquent.
Also, I have seen other's answer where people have suggested to order directly in model like:
public function company()
{
return $this->belongsTo('App\Models\Company')->orderBy('name');
}
But, I don't want to order direclty on model because I don't want it to be ordered by name everytime. I want to leave it to default.
Also, on some other scenario, I saw people using join combining with, but I am not really impressed with using both join and with to load the same model.
What is the best way to solve my problem?
I have table like: companies: id, name, properties: id, property_name, company_id, notices: title, slug, body, property_id
The issue here is that the Property::with(['company','notices']); will not join the companies or notices tables, but only fetch the data and attach it to the resulting Collection. Therefore, neither of the tables are part of the SQL query issued and so you cannot order it by any field in those tables.
What Property::with(['company', 'notices'])->get() does is basically issue three queries (depending on your relation setup and scopes, it might be different queries):
SELECT * FROM properties ...
SELECT * FROM companies WHERE properties.id in (...)
SELECT * FROM notices WHERE properties.id in (...)
What you tried in the sample code above is to add an ORDER BY company_name or later an ORDER BY companies.name to the first query. The query scope knows no company_name column within the properties table of course and no companies table to look for the name column. company.name will not work either because there is no company table, and even if there was one, it would not have been joined in the first query either.
The best solution for you from my point of view would be to sort the result Collection instead of ordering via SQL by replacing $records = $query->get(); with $records = $query->get()->sortBy($order, $dir);, which is the most flexible way for your task.
For that to work, you would have to replace 'company_name' with 'company.name' in your $columns array.
The only other option I see is to ->join('companies', 'companies.id', 'properties.company_id'), which will join the companies table to the first query.
Putting it all together
So, given that the rest of your code works as it should, this should do it:
$columns = [
'company.name',
'property_name',
'amenity_review',
'pricing_review',
'sqft_offset_review',
'created_at',
'last_uploaded_at',
];
$totalData = Property::count();
$limit = $request->input('length');
$start = $request->input('start');
$order = $columns[$request->input('order.0.column')];
$dir = $request->input('order.0.dir');
$query = Property::with(['company', 'notices']);
$company_search = $request->columns[0]['search']['value'];
$property_search = $request->columns[1]['search']['value'];
if (!empty($company_search)) {
$query->whereHas(
'company', function ($query) use ($company_search) {
$query->where('name', 'like', $company_search . '%');
});
}
if (!empty($property_search)) {
$query->where('properties.property_name', 'like', $property_search . '%');
}
if (!Auth::user()->hasRole('superAdmin')) {
$query->where('company_id', Auth::user()->company_id);
}
if ($limit != '-1') {
$records = $query->offset($start)->limit($limit);
}
$records = $query->get()->sortBy($order, $dir);
I'd like to know the position of a user based on its creation date. How do I do that using Eloquent?
I'd like to be able to do something like this:
User::getRowNumber($user_obj);
I suppose you want MySQL solution, so you can do this:
DB::statement(DB::raw('set #row:=0'));
User::selectRaw('*, #row:=#row+1 as row')->get();
// returns all users with ordinal 'row'
So you could implement something like this:
public function scopeWithRowNumber($query, $column = 'created_at', $order = 'asc')
{
DB::statement(DB::raw('set #row=0'));
$sub = static::selectRaw('*, #row:=#row+1 as row')
->orderBy($column, $order)->toSql();
$query->remember(1)->from(DB::raw("({$sub}) as sub"));
}
public function getRowNumber($column = 'created_at', $order = 'asc')
{
$order = ($order == 'asc') ? 'asc' : 'desc';
$key = "userRow.{$this->id}.{$column}.{$order}";
if (Cache::get($key)) return Cache::get($key);
$row = $this->withRowNumber($column, $order)
->where($column, '<=',$this->$column)
->whereId($this->id)->pluck('row');
Cache::put($key, $row);
return $row;
}
This needs to select all the rows from the table till the one you are looking for is found, then selects only that particular row number.
It will let you do this:
$user = User::find(15);
$user->getRowNumber(); // as default ordered by created_at ascending
$user->getRowNumber('username'); // check order for another column
$user->getRowNumber('updated_at', 'desc'); // different combination of column and order
// and utilizing the scope:
User::withRowNumber()->take(20)->get(); // returns collection with additional property 'row' for each user
As this scope requires raw statement setting #row to 0 everytime, we use caching for 1 minute to avoid unnecessary queries.
$query = \DB::table(\DB::raw('Products, (SELECT #row := 0) r'));
$query = $query->select(
\DB::raw('#row := #row + 1 AS SrNo'),
'ProductID',
'ProductName',
'Description',
\DB::raw('IFNULL(ProductImage,"") AS ProductImage')
);
// where clauses
if(...){
$query = $query->where('ProductID', ...));
}
// orderby clauses
// ...
// $query = $query->orderBy('..','DESC');
// count clause
$TotalRecordCount = $query->count();
$results = $query
->take(...)
->skip(...)
->get();
I believe you could use Raw Expresssions to achieve this:
$users = DB::table('users')
->select(DB::raw('ROW_NUMBER() OVER(ORDER BY ID DESC) AS Row, status'))
->where('status', '<>', 1)
->groupBy('status')
->get();
However, looking trough the source code looks like you could achieve the same when using SQLServer and offset. The sources indicates that if you something like the following:
$users = DB::table('users')->skip(10)->take(5)->get();
The generated SQL query will include the row_number over statement.
[For Postgres]
In your model
public function scopeWithRowNumber($query, $column = 'id', $order = 'asc'){
$sub = static::selectRaw('*, row_number() OVER () as row_number')
->orderBy($column, $order)
->toSql();
$query->from(DB::raw("({$sub}) as sub"));
}
In your controller
$user = User::withRowNumber()->get();
I need to build this query in Codeigniter but I don't know how to get the result of the SUM:
SELECT
description, SUM(amount)
FROM
PAYMENT
WHERE
(date_payment between '2014-02-01 00:00:00' AND '2014-02-28 23:59:59')
GROUP BY description;
I'm trying to get the result with this:
$qwer = $this->db->query("
SELECT description, SUM(amount)
FROM PAYMENT
WHERE (date_payment between '$min_date' AND '$max_date')
GROUP BY description;");
$i = 0;
foreach ($qwer->result() as $payment) {
$det_payment[$i] = array(
'description'=>$payment->description,
'amount'=>$payment->amount
);
$i++;
}
Of course "$payment->amount" is wrong, but if I use an alias for the SUM, the model doesn't work.
EDIT: Right now I can choose between the description or the sum, but I can't use both select and select_sum
$this->db->select('description');
//$this->db->select_sum('amount', 'amount');
$this->db->where('date_payment >=', $min_fecha);
$this->db->where('date_payment <=', $max_fecha);
$this->db->group_by("description");
$qwer = $this->db->get('PAYMENT');
Setting FALSE as second parameter, 'select' allows to write a custom sentence.
$this->db->select('description, SUM(amount) AS amount', FALSE);
$this->db->where('date_payment >=', $min_date);
$this->db->where('date_payment <=', $max_date);
$this->db->group_by("description");
$qwer = $this->db->get('PAYMENT');
Documentation for CI2
Documentation for CI3
try something like this:
$query = $this->db->select_sum('amount', 'Amount');
$query = $this->db->where(...)
$query = $this->db->get('payment');
$result = $query->result();
return $result[0]->Amount;