I am trying to get a row which have latest created time,
Example, i have table with news_id, news_content, news_postedon. This table have 10 rows of data,
Now i want to pull row which have latest time of new_postedon,
I am using codeigniter,
I added below code,
function view_latestnews()
{
$this->db->join('sc_users', 'sc_users.user_id = sc_news.news_postedby');
$this->db->select_max('news_postedon');
return $this->db->get('sc_news')->row();
}
By using this function i got only value of news_posted on which is max like (stdClass Object ( [news_postedon] => 2015-04-12 21:28:21 )),
But i could not get value of news_content
How can i get complete row which have latest time of posted using codeigniter?
Thanks in advance
Try
function view_latestnews()
{
$this->db->join('sc_users', 'sc_users.user_id = sc_news.news_postedby');
$this->db->where('news_postedon = (SELECT max(news_postedon) FROM sc_news)');
return $this->db->get('sc_news')->row();
}
Related
I am trying to make an array with posts in them, now, i need to insert the posts into the array based on their post date, eg if a post was posted on day 4 it will come after the post that was posted on day 5, so the newest posts gets added and displayed first, is there a good way to do this?
The easiest and not right method at all:
$sortedNews = []; //sorted news
foreach($newsArray as $news) {
$sortedNews[strtotime($news['date'])] = $news; //take date and switch to unix timestamp as key of value
}
krsort($sortedNews); //sort by key (reverse) new to old
The right way it's let your database sort it itself ORDER BY `date` DESC
Below I have stripped down my code to a simplified version. I am storing SQL SELECT results for:
last name (dlname)
category (category)
date this data was added to database (date_added)
clients name (client)
I have appended an additional field outside the SQL SELECT called 'days_on_list'. This field shows the number of days since the data was added to the database, making the table output 5 columns of user data. ALL 5 COLUMNS ARE TO BE SORTABLE.
I am using server-side JSON and have successfully been able to display this to the table and perform sorting on 4 of the 5 columns. The problem is that I am unable to sort the 'days_on_list' field as the PHP file containing the SQL code only allows me to sort the 4 fields from the select query. Is there a way I can make 'days_on_list' column be sortable in the table? I know I can add this field to the sql table, but I would have to run a scheduled event on the server to update this daily (which I am not comfortable with).
Is there another way to allow for this kind of flexible table sorting?
Sorry about the question title (may be confusing), I was having trouble putting this into a question.
/*SQL CODE ABOVE HERE STORES SELECT RETURNS IN $result*/
$cart = array();
$i = 0; //index the entries
// get variables from sql result.
if ($num_rows > 0) { //if table is populated...
while ($row = mysqli_fetch_assoc($result)) {
//calculate days on list by getting the number of days from
//the 'date_added' to today
$date1 = date_create($row['date_added']);
$today = date_create(date("d-m-Y"));
$interval = date_diff($date1, $today);
$doty = $interval - > format("%a");
$cart[$i] = array(
"dlname" => htmlspecialchars($row['dlname']),
"category" => htmlspecialchars($row['category']),
"date_added" => htmlspecialchars($row['date_added']),
"client" => htmlspecialchars($row['client']),
"days_on_list" => $doty, //date_added to now
);
$i = $i + 1; //add next row
}
//encoding the PHP array
$json_server_pagination_data = array(
"total" => intval($num_rows),
"rows" => $cart, //array data
);
}
echo json_encode($json_server_pagination_data);
Because days_on_list is calculated by simply comparing date_added to the current date, sorting by days_on_list should have exactly the reverse effect as sorting by date_added.
In other words, you don't actually need to sort by days_on_list. If the user selects days_on_list as the sort column, just use ORDER BY date_added (in the opposite direction ASC/DESC).
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.
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.
Current situation
I have two tables in my database, one for posts, and one for ratings. These are linked with a relation in the MySQL so that one post may have 0, 1 or multiple ratings, but one rating can only be applied to one post.
When I fetch a list of posts, I also want to get ratings, but without having to make a separate call to the database for each post in the foreach loop.
To do this I have attempted to use an SQL query to fetch all posts with a LEFT JOIN on ratings so that it will return a result like this:
statusId|statusBody|rating
-----------------------------
1, post1, 0
1, post1, 1
2, post2, 0
3, post3, 1
3, post3, 1
The SQL works fine, and I get the data I ask for.
Ideally what I am trying to achieve now is to turn this table into a collection of objects, with each object storing the post information as well as a value depending on it's total ratings.
After using PDO to return the data result, this is the code I am using to map the data:
Code Logic
The logic of my code goes like this:
Get all statuses joined with ratings table
Create empty output array
Loop through PDO result
{
Create loop specific temp array
Push first row of result into temp array
Remove row from PDO result
Loop through PDO result for objects with matching statusId
{
If row matches statusId, add to temp buffer and remove from PDO result
}
Take first row of buffer and create status object
Loop through objects in temp array to calculate ratings and add onto above status object
Clear temp buffer
Add status object to output array
}
return output array
Actual Code
try
{
$result = $pdo->query($sql);
//if($result == false) return false;
$statuses = $result->fetchAll(PDO::FETCH_CLASS, 'status');
}
catch (PDOException $e)
{
return FALSE;
}
if (!$result) {
return FALSE;
}
//create empty output array to be filled up
$status_output = array();
//loop through all status
foreach($statuses as $s1key => $s1value)
{
//initialise temporary array;
$status_temp_buffer = array();
//create temp array for storing status with same ID in and add first row
array_push($status_temp_buffer, $s1value);
//remove from primary array
unset($statuses[$s1key]);
//loop through array for matching entries
foreach($statuses as $s2key => $s2value)
{
//if statusId matches original, add to array;
if($s2value->statusId == $s1value->statusId)
{
//add status to temp array
array_push($status_temp_buffer, $s2value);
//remove from primary array
unset($statuses[$s2key]);
}
//stop foreach if statusId can no longer be found
break;
}
//create new status object from data;
$statObj = $status_temp_buffer[0];
//loop through temp array to get all ratings
foreach($status_temp_buffer as $sr)
{
//check if status has a rating
if($sr->rating != NULL)
{
//if rating is positive...
if($sr->rating == 1)
{
//add one point to positive ratings
$statObj->totalPositiveRatings++;
}
//regardless add one point to total ratings
$statObj->totalAllRatings++;
}
}
//clear temporary array
$status_temp_buffer = NULL;
//add object to output array
array_push($status_output, $statObj);
}
Problem
The problem I am coming up against with this code is that although the ratings are fine, and it correctly calculates the ratings total for each post, it still shows duplicates where a post has more than one rating.
Any help with this would be greatly appreciated,
Thanks
As i understood it, the goal is to get the total rating of each Post entry. Instead of manually looping over each and every rating, there are two other path you could take:
compute the total in the query:
SELECT SUM(rating) AS total , .. FROM Posts LEFT JOIN .... GROUP BY statusID
You will receive a list of Post entries, each already with total rating calculated. This is a very good solution if you have a lot of writes to to the Ratings table, and much less reads.
the other way is to break the table normalization, but to increase read performance. What you would have to do is to add another column in the Posts table: total_rating. And have an TRIGGER on INSERT in the Ratings table, which changes the Posts.total_rating accordingly.
This way has a benefit of simplifying the request of Posts. At the same time Ratings table can now be use to ensure that total_rating has been calculated correctly, or to recalculate the value, if there are some large changes in the ratings: like banning of user, which results in removing all ratings made by this user.