i am trying to covert this query in active record
SELECT
crm_clients.id,
crm_clients.`moved_date`,
crm_clients.`contractor_id`
FROM
dev_pfands.`crm_clients`
WHERE crm_clients.`contractor_id` = 11
AND (
crm_clients.`status` = 9
OR crm_clients.`status` = 8
OR crm_clients.`status` = 7
)
AND crm_clients.id IN
(SELECT
crm_client_cheques.`client_id`
FROM
dev_pfands.`crm_client_cheques`)
AND crm_clients.`moved_date` BETWEEN '2014-08-01'
AND '2014-11-29 '
AND crm_clients.`contractor_id`<>''
GROUP BY crm_clients.`id
the section I'm having issue is
AND crm_clients.id IN
(SELECT
crm_client_cheques.client_id
FROM
dev_pfands.crm_client_cheques) `
i've tried the where_in method but overtime i try to include my attempt of $this ->db_pfands -> where('crm_client_cheques.client id' ,'id'); get hit with errors and have no idea how to get past this.
the original query should return 703 rows and when I've removed the part I'm stuck with it increase to 3045 so i need it to be included. any help is appreciated.
First of all you have a error in your code.
$this->db_pfands->where('crm_client_cheques.client id', 'id');
This will be
$this->db_pfands->where('crm_client_cheques.client_id', 'id');
You have to provide the right column name and as far i know database's column name have not contain any space.
Now I think this active record query will help you to get your result.
$query = $this->db->select('crm_clients.id, crm_clients.moved_date, crm_clients.contractor_id')
->where('moved_date BETWEEN "2014-08-01" AND "2014-11-29"')
->where('contractor_id', 'id')
->where_in('status', [9,8,7])
->from('crm_clients')
->join('crm_client_cheques', 'crm_client_cheques.client_id = crm_clients.id')
->group_by('id')
->get();
$result = $query->result();
May be you have change couple of names because they are in different database, but i believe you can do it.
Related
I am using server-side rendering in DataTable.
I have a variable that determines limit to number of rows from database.
I am trying to fetch, say, 100 rows, and from DataTable with pagelength of 25, paginate it upto 4 pages.
Also, if the limit variable is 4 or 10, or anything less than pagelength value, then all records will be displayed in a single page.
Here's my code:
#get datatable params
$draw = $this->request->input('draw');
$start = $this->request->input('start');
$dt_limit = $this->request->input('length'); // datatable pagination limit
$limit_rows = $this->request->input('limit');
# query
$result_product_urls = DB::table('product_match_unmatches')
->select('r_product_url', 'r_image_url_main')
->selectRaw('count(distinct s_product_url, r_product_url) as frequency,
GROUP_CONCAT(CONCAT(s_image_url, "&s_product_url=", s_product_url) SEPARATOR " | ") as source_products')
->groupBy('r_product_url')
->where('request_id', '=', $reqId)
->orderBy('frequency', 'DESC')
->take($limit_rows);
$recordsTotal = $result_product_urls->get()->count();
$urls = $result_product_urls->offset($start)->limit($dt_limit)->get();
This will always fetch 25 rows from the database, since the dataTable page-length is 25.
But I need to limit the rows based on $limit_rows value, and not $dt_limit.
If I only do $urls = $result_product_urls->get();, then if $limit_rows value is 100, all 100 rows are displayed in the same page.
How can I fetch limit rows from database, and then paginate through it?
I hope I make my post clear.
I'll take a stab at this, but it's not entirely clear to me the exact thing you are attempting to accomplish based on the code sample.
According to Laravel docs take and limit appear to be equivalent.
https://laravel.com/docs/5.8/queries#ordering-grouping-limit-and-offset (bottom of this section)
What it looks like the code is doing:
Using $limit_rows value with ->take() method in the $result_product_urls query builder object:
# query
$result_product_urls = DB::table('product_match_unmatches')
->select('r_product_url', 'r_image_url_main')
->selectRaw('count(distinct s_product_url, r_product_url) as frequency,
GROUP_CONCAT(CONCAT(s_image_url, "&s_product_url=", s_product_url) SEPARATOR " | ") as source_products')
->groupBy('r_product_url')
->where('request_id', '=', $reqId)
->orderBy('frequency', 'DESC')
->take($limit_rows); /* <------------- limit_rows HERE */
But then also using $dt_limit value with ->limit() method when setting the $urls variable:
$recordsTotal = $result_product_urls->get()->count();
$urls = $result_product_urls->offset($start)->limit($dt_limit)->get();/*<-- dt_limit HERE */
If you don't want to use $dt_limit as a limit then don't use it...? I think maybe what you are trying to do is have a query with a limit on the result set, and then a sub limit on that? I can't figure out a reason to want to do that, so I might be missing something. I don't think you can use ->take() and ->limit() on the same query.
Shouldn't this accomplish your goal?:
# query
$result_product_urls = DB::table('product_match_unmatches')
->select('r_product_url', 'r_image_url_main')
->selectRaw('count(distinct s_product_url, r_product_url) as frequency,
GROUP_CONCAT(CONCAT(s_image_url, "&s_product_url=", s_product_url) SEPARATOR " | ") as source_products')
->groupBy('r_product_url')
->where('request_id', '=', $reqId)
->orderBy('frequency', 'DESC');
/* ->take($limit_rows); remove this */
$recordsTotal = $result_product_urls->get()->count();
$urls = $result_product_urls->offset($start)
->limit($limit_rows) /* set limit to $limit_rows */
->get();
If not, then maybe you can clarify.
use offset alongwith limit i.e.
$users = DB::table('users')->skip(10)->take(5)->get();
or
$users = DB::table('users')->offset(10)->limit(5)->get();
SO I want to find that if value x is exits between the values of 2 columns or not, For that i have run the query in phpmyadmin :
Normal Approch :-
SELECT * FROM `traits_versions` WHERE 16 BETWEEN `trait_value_lower` and `trait_value_upper` and `style_id` = 1
and it is giving me fine result.But when the same approach i want to find achieve in YII that it is not running and giving the sql error :
YII apprroch :-
$details = array();
$criteria = new CDbCriteria();
$criteria->addCondition('style_id='.$style_id);
$criteria->addCondition('version='.$version);
$criteria->addBetweenCondition($style_contribution,$this->trait_value_lower,$this->trait_value_upper);
$trait_details= $this->find($criteria);
When i debug the query in log than it shows in case of yii :
SELECT * FROM `traits_versions` `t` WHERE ((style_id=1) AND (version=1)) AND (16 BETWEEN NULL AND NULL) LIMIT 1
Why it is giving NULL value in query while i'm passing the name of the column in it.
So please guide me where i'm going wrong in yii.
Add compare condition like below
$criteria->compare('trait_value_lower', 16, false, '>');
$criteria->compare('trait_value_upper',16, false, '<');
instead of between condition
$criteria->addBetweenCondition($style_contribution,$this->trait_value_lower,$this->trait_value_upper);
because between condition will apply on one column as per Yii doc.
public static addBetweenCondition(string $column, string $valueStart, string $valueEnd, string $operator='AND')
I am facing a problem. I have to update a field in database by using cron function in moodle. I am using update query in cron function to update value. But It doesn't work. I am using this function to update value:
function activitysetmodule_cron ()
{
global $CFG, $DB;
$DB->update_record("activitysetmodule",)
$sql="update {$CFG->prefix}activitysetmodule as asm set status = 1 where exists (select 1 from {$CFG->prefix}course_modules as cm where (module=asm.activityset OR module=asm.activityset2 ) AND completion=1 AND asm.course =cm.course ");
return true;
}
Please help to sought it out.
Take a look at the documentation https://docs.moodle.org/dev/Data_manipulation_API#Updating_Records
$DB->update_record takes 2 params, the name of the table to update the record in and an object containing the updated data.
e.g.
$obj = new stdClass();
$obj->id = $id_of_object_to_update;
$obj->status = 1;
$DB->update_record('tablename', $obj);
It looks like you should refactor your code to get a list of records to update, then call $DB->update_record on each in turn (or $DB->set_field, if there is only one field to update). Alternatively, you could use the $DB->execute($sql) function to directly run some SQL on the server, e.g.
$DB->execute("UPDATE {activitysetmodule} asm SET status = 1 WHERE EXISTS (SELECT 1 FROM {course_modules} cm WHERE (module=asm.activityset OR module=asm.activityset2 ) AND completion=1 AND asm.course = cm.course)");
Note the use of {tablename} rather than {$CFG->prefix}tablename and the removal of the 'AS' keyword, as that is not allowed on all DB engines.
Note also, if you haven't done so already, turning on debugging (http://docs.moodle.org/en/Debugging) will give you much more helpful error messages.
I have this CodeIgniter query, which is working almost as intended..
$this->db->select()
->from('user_issues')
->where(array('user_issues.user_id' => $user_id))
->join('issue_properties', 'user_issues.issue_id = issue_properties.issue_id')
->join('series_properties', 'issue_properties.series_id = series_properties.series_id')
->join('user_issues_count', 'user_issues_count.series_id = series_properties.series_id')
->group_by('issue_properties.series_id')
->order_by('series_properties.name')
->offset($offset)->limit($per_page);
}
The query is supposed to return data specific to a users comic collection, the final join is just grabbing the first record it finds that matches, regardless of the user_id.
Is it possible to do something like the AND join in CodeIgniter or a WHERE statement perhaps?
join('user_issues_count', 'user_issues_count.series_id = series_properties.series_id' WHERE 'user_issues_count.user_id = $user_id')
You can add a new where condition wherever it is semantically appropriate in the Active Record Query.
$this->db->select()
->from('user_issues')
->where(array('user_issues.user_id' => $user_id))
->join('issue_properties','user_issues.issue_id = issue_properties.issue_id')
->join('series_properties', 'issue_properties.series_id = series_properties.series_id')
->join('user_issues_count','user_issues_count.series_id = series_properties.series_id')
->where("user_issues_count.user_id = ".$user_id) //new WHERE condition
->group_by('issue_properties.series_id')
->order_by('series_properties.name')
->offset($offset)
->limit($per_page);
The idea is to mix and match the Active Record Functions and print the SQL to see the effect - and tweak them until you get the SQL you require...
I have an update record that looks like this
$data_gallery = array(
'order' => $value
);
$this->db->where('order', $newOrder);
$this->db->update('gallery', $data_gallery);
I have say, 5 images I have reorderd. I have their old position and their new position.
But as I loop through they sometime overwrite each other.
Example:
5 images 1,2,3,4,5
I change the order 2,1,3,4,5
I update in the loop as it goes through the array of new order.
Update order = 2 where order = 1
Update order = 1 where order = 2
Obviously the second one never gets hit as order = 2 no longer exits.
I guess this more a logic question than anything else.
Any ideas how I can easily loop through and update without losing some of the data? I though maybe updating in a batch operation but didn't get very far with it.
Thanks in advance.
Use the image's ID in your WHERE clause:
$this->db->where('imageid', $imageid);
This will set the new order to each image without previously overwriting (and disappearing!) any information.
Check if you have any other fields to check for your criteria to match the exact records.
$data_gallery = array(
'order' => $value
);
$this->db->where('order', $newOrder);
//check if you have any other fields to match also image id, record id or any other ids to match
$this->db->where('second_id',$second_id);
$this->db->update('gallery', $data_gallery);