Sort months array by position - php

I need to sort an array of months (alphabetical months) according to their months position and not alphabetical. My script returns a list of events and builds an multi-associative arrays based on years => months e.g. 2012 => array("August","March","September"), 2013 => array("April","May"); It builds the array perfectly, but I now need to sort the months so that it would return 2012 => array("March","August","September"), 2013 => ("April","May);
Here is the script I am currently using. Note that the date field in mysql is set to DATE and not VARCHAR, and dates are entered YYYY-MM-DD
public function returnMonthsArray() {
$sql = "SELECT `date` FROM `events` WHERE `status`=1 ORDER BY `name`";
$results = $this->db->returnMultiAssoc($sql);
$navArray = array();
foreach($results as $key => $value) {
$timestamp = strtotime($value["date"]);
$year = date("Y",$timestamp);
$month = date("F",$timestamp);
if(!array_key_exists($year, $navArray)) {
$navArray[$year] = array();
}
if(!in_array($month,$navArray[$year])) {
$navArray[$year][] = $month;
}
}
if(count($navArray)) {
return $navArray;
} else {
return false;
}
}

try this query
SELECT `date` FROM `events`
WHERE `status`=1 ORDER BY `name`"
GROUP BY MONTH(`date`)

Have a look to this post:
PHP and Enums
By specifing an enum like behavior for the months it would be easier to sort them the way that you want.
I hopw that this is helpful to you.

Related

Getting MySQL results based on date by current month in Codeigniter

I currently get the last 30 days results like this.
public function commission_month(){
$status = 'A';
$this->db->select_sum('LenderCommission');
$this->db->where(['Status' => $status ]) ;
$this->db->where('CompletedDate >= DATE_SUB(CURDATE(), INTERVAL 30 DAY) ');
$query = $this->db->get('toutcome');
$result = $query->result();
return $result[0]->LenderCommission;
}
What i am really trying to do is get results for this current month.
And then when its the next month , its should do the same.
You can use a "like" query to get the information you need, assuming the dates are stored in a manner you can easily apply a like to.
Basically, the query will be something along the lines of ... AND CompletedDate LIKE 'YYYY-MM-%'... where YYYY and MM are valid year and months. This can be done in CodeIgniter by using the $this->db->like() builder:
$this->db->like('CompletedDate', date('Y-m'));
Your code then being:
public function commission_month(){
$status = 'A';
$this->db->select_sum('LenderCommission');
$this->db->where(['Status' => $status ]) ;
$this->db->like('CompletedDate', date('Y-m'));
$query = $this->db->get('toutcome');
$result = $query->result();
return $result[0]->LenderCommission;
}

Mysql and PHP frequency based on time

I am working on a project to graph frequency over a time period. The server currently stores all the data I need apart from the count as this will change over time. I am pulling all of the data that I need using the following code:
<?php
$con = mysql_connect("127.0.0.1",xxx,xxx);
if (!$con) {
die('Could not connect: ' . mysql_error());
}
mysql_select_db("tweets", $con);
$results = array();
$result = mysql_query("SELECT company, time FROM data WHERE company = 'AAPL'");
while($row = mysql_fetch_array($result))
{
$results[] = $row;
}
$results = json_encode($results);
mysql_close($con);
echo $results;
?>
When returned I have an array that contains all of the company names and times. how would I go about counting the frequency within a time frame, for example the frequency in the past 24 hours and then a separate value for the previous 24 hours?
You just loop through the data, the exact code depends on the format of the time and the format of the result required. You could do something like this :
$summary =array();
foreach($results as $result)
{
$day = substring($result['time'], 0, 10);
if(isset($summary[$day])){
$summary[$day]++;
} else {
$summary[$day] = 1;
}
}
Write the function getDay() according to the format of the time.
If your date/time values are stored as MySQL datetime (and for your sake I hope they are) then the solution is trivial. Select records within a certain time period and group by company, e.g.
SELECT
`company`, COUNT(`company`) AS total
FROM
`data`
WHERE
`time` >= now() - INTERVAL 1 DAY
GROUP BY
company
In this example I use MySQL to compute the 24 hour period, but you could just as easily have PHP compute an exact time/date.
If you want a pure PHP solution, then start by storing your times grouped by companies in a multidimensional array. Convert your times from your DB format to Unix time. In my example I use strtotime(); if your db times are in a funky format then you'll need to do something else to convert them.
$result = mysql_query("SELECT company, time FROM data");
while($row = mysql_fetch_array($result)) {
$results[$row['company']] = strtotime($row['time']);
}
Then simply loop the array and evaluate.
// 24 hours before now
$start = time() - ( 24*60*60);
$lastTwentyFourHours = array();
foreach ( $results as $company => $times ) {
if ( !isset($lastTwentyFourHours[$company]) ) {
$lastTwentyFourHours[$company] = 0;
}
foreach ( $times as $time ) {
if ( $time >= $start ) {
$lastTwentyFourHours[$company]++;
}
}
}
print_r($lastTwentyFourHours);

Echo 0 for Mysql query with no results

I'm building an array of the number of calls I have for a particular client from a mysql db on a running list of the last 30 days. The code I have so far works for adding the days that have calls to the array but I need a show a '0' for the days that have no calls (no entries in the db). Here is me code so far:
$query="SELECT COUNT(*) FROM my_db WHERE client_phone='clint_phone#' GROUP BY calldate";
$result = mysql_query($query);
$data = array();
while ($row = mysql_fetch_row($result)) {
$data[] = $row[0];
}
I just need a way to show if today I had 30 calls and yesterday I had 0, I need it to show [30,0]. What I have only would show [30].
EDIT * I have a mysql db will columns client_phone, calldate. Im looking to build a graph using the data in an array. Each point of the graph will represent a day and the number of calls for that client on that day. Im building the above query to populate that array. I'm trying to count backwards thirty days and feed the total calls for each day into the array.
EDIT 2* I've got it almost there. I'm getting a problem in the 'foreach' area. Below is the code with two print_r()'s to dump the array. The first one looks good, but the second one shows some array entries getting over-written that shouldn't be:
$query="SELECT calldate, COUNT(*) FROM my_db WHERE client_phone='phone#' and calldate>='20130101' AND calldate<='20130107' GROUP BY calldate ORDER BY calldate";
$result = mysql_query($query);
$data = array();
while ($row = mysql_fetch_array($result)) {
$data[$row['calldate']] = $row[1];
}
$startDate = '20130101';
$endDate = '20130107';
$dates = array();
for($current = $startDate; $current != $endDate; $current = date('Ymd', strtotime("$current +1 day"))) {
$dates[] = $current;
}
$dates[] = $endDate;
print_r ($data);
echo "<br />";
foreach($dates as $date){
if (in_array($date, $data)) {
// that date was found in your db_date array(therefore had queries)
}else{
$data[$date] = 0; //date was not found in your db_array so we set that date with no queries to zero
}
}
print_r ($data);
I run this in a browser and I get this:
Array ( [20130101] => 1 [20130104] => 6 [20130105] => 2 [20130106] => 1 [20130107] => 3 )
Array ( [20130101] => 0 [20130104] => 0 [20130105] => 0 [20130106] => 0 [20130107] => 0 [20130102] => 0 [20130103] => 0 )
The top output looks good, just missing a zero assigned to dates not in the data[] array. The second array has zero's in the missing dates, but other overwrited that shouldn't have been.
Thanks for any help!
Finding every date that is in that timespan and doing a task for that does not really that standard of a solution. But depending if your host allows cron-tasks; if you were able to use cron tasks to automatically insert a 0 into your database at 11:59pm for that date if no querys were made that day; you could simply extract all dates.
If you do not want to do it with cron tasks I think you can manage it this way...
$startDate = '2009-01-28';
$endDate = '2009-02-04';
$dates = array();
for($current = $startDate; $current != $endDate; $current = date('Y-m-d', strtotime("$current +1 day"))) {
$dates[] = $current;
$dates[] = $endDate;
}
then do this
foreach($dates as $date){
if (array_key_exists($date, $data)) {
// that date was found in your db_date array(therefore had queries)
}else{
$data[$date] = 0; //date was not found in your db_array so we set that date with no queries to zero
}
}
This may need some minor adjustments because I have not tested it; but this should work; if not something very close to it should. Hope this helps.

find the upcomming birthday in week [duplicate]

This question already has answers here:
Closed 11 years ago.
Possible Duplicate:
How would I get the birthdays of friends who are celebrating their birthday this week, this month and next month using MYSQL and PHP?
I have a mysql table of users with fields UserId, Username, Birthdate (format YYYY-MM-DD). I want to display something on my homepage like this:
Upcoming birthdays:
Fred Smith 24 Aug
Bill Jones 27 Aug
Sarah Connor 1 Sep
David Cassidy 5 Sep
You get the idea - it generates a short list of which birthdays are coming up next, ignoring the year, just based on the day and month. I just have no idea how to do the query - any help would be appreciated!
You can use the mysql DATE_FORMAT() function. This should give you all the birthdays between the current day, and 7 days from now:
SELECT username, DATE_FORMAT(Birthdate,'%M %d') as 'birthday' FROM table WHERE DATE_FORMAT(Birthdate,'%m-%d') BETWEEN DATE_FORMAT(CURDATE(),'%m-%d') AND DATE_FORMAT(ADDDATE(NOW(), INTERVAL 7 DAY), '%m-%d') ORDER BY DATE_FORMAT(Birthdate,'%m-%d');
Another option is to create a function that will sit in a helper class, or go into your user class perhaps:-
/**
* Fetches a list of birthdays coming up in the following week
* #return array an array user's birthdays
*/
public function getBirthdays()
{
$date = new DateTime();
$date->setTime(0, 0, 1);
$today = $date->getTimestamp();
$week = new DateInterval('P7D');
$date->add($week);
$date->setTime(23, 59, 59);
$nextWeek = $date->getTimestamp();
$select = new Zend_Db_Select(Zend_Db_Table::getDefaultAdapter());
$select ->from('users', array('user_name', 'user_dob'))
->where('user_dob > ?', $today)
->where('user_dob < ?', $nextWeek);
return $select->query()->fetchAll();
}
Then you just do:-
$birthdays = $classYouMade->getBirthdays();
$html = '';
foreach($birthdays as $bday){
$html .= "Happy Birthday to {$bday['user_name']} on ";
$html .= date('jS F', $bday['user_dob']) . '<br/>';
}
echo $html;
It's quite long, but is self documenting (I think) and you can come back to it in a year's time and see exactly what is happening at a glance.
I have ofcourse made some assumptions about how you are storing date etc (I always use unix timestamps), but I'm sure you can adapt it to your use case if you wish to use it.
First, you need to retrieve a list of your users as follow:
$adapter = Zend_Db_Table::getDefaultAdapter()
$table = $adapter->getDbTable()
$select = $table->select();
$select->where('active = ?', true); // if needed
$user = $table->fetchAll($select);
Your getDbTable would be something very similar to the one in Zend Quickstart :
public function setDbTable($dbTable)
{
if (is_string($dbTable)) {
$dbTable = new $dbTable();
}
if (! $dbTable instanceof Zend_Db_Table_Abstract) {
throw new Exception('Invalid table provided');
}
$this->_dbTable = $dbTable;
return $this;
}
public function getDbTable()
{
if (null === $this->_dbTable) {
$this->setDbTable('My_Users_DbTable_User');
}
return $this->_dbTable;
}
And in My/Users/DbTable/User a simpla class that contains:
class My_Users_DbTable_User extends Zend_Db_Table_Abstract
{
protected $_name = 'users';
}
Finally, when you retrieved your data from the database, you can iterate through each row you fetched using current() and toArray()methods. See Zend_Db_Table_Row documentation for more details.
In order to display only the day and month of a birthdate, you can use Zend_Date which is pretty useful.
$date = "1970-12-10";
$d = new Zend_Date($date);
echo $d->toString(Zend_Date::DAY) . " " . $d->toString(Zend_Date::MONTH_NAME_SHORT);
// output: 10 Dec
You can query this with something like:
SELECT username, birthdate FROM table WHERE birthdate >= beginning_of_week AND birthdate <= end_of_week
You'd probably have to calculate the week range you want in whatever script you're querying from.
You should be able to get the list with a simple SQL query:
select UserId, Username, Birthdate from Users where Birthdate >= CURDATE() and Birthdate <= DATE_ADD(CURDATE(), INTERVAL + 2 WEEK) order by Birthdate ASC
Then you can format the text using DateTime::format() in PHP.
while ($row = mysql_fetch_assoc($res))
{
$birthday = new DateTime($row['Birthdate']);
print $row['Username']." ".$birthday->format('d M')."\n";
}

creating archive for my blog website

my database table is something like :
id year month
1 2011 november
2 2011 november
3 2011 october
i need to create a query so it return something like that :
2011
november
november
october
What is the correct query syntax to do it in php script ?
Here is the code i used :
<?php
$uid = $_SESSION['uid'];
$sql = "SELECT year, GROUP_CONCAT(month) AS months FROM articles GROUP BY year";
$res = mysql_query ($sql) or die (mysql_error());
if (mysql_num_rows($res) > 0) {
while ($rows = mysql_fetch_assoc($res)) {
foreach ($rows AS $row) {
echo $row['year'] . "<br>";
$months = explode(",", $row['months']);
foreach ($months AS $m) {
echo $m . "<br>";
}
}
}
}
?>
You can use GROUP_CONCAT() to return a comma-separated list of months:
SELECT year, GROUP_CONCAT(month) AS months GROM tbl GROUP BY year
Returns:
2011 november,november,october
Or just select both columns and handle the display/presentation in your code:
SELECT year, month FROM tbl WHERE year = 2011
Returns
2011 november
2011 november
2011 october
In code, loop and only display the year when it changes.
Update Since a code example seems warranted...
// Results from above GROUP_CONCAT() query already fetched & stored in `$rowset`:
while ($row = mysql_fetch_assoc($res)) {
$rowset[] = $row;
}
// Now $rowset is a 2D array containing all rows.
foreach ($rowset as $row) {
// Output the year
echo $row['year'] . "\n";
// months are comma-separated via GROUP_CONCAT()
// explode them into an array
$months = explode(",", $row['months']);
foreach ($months as $m) {
// Output the months
echo $m . "\n";
}
}
If I understood your question correctly, I think a simple "ORDER BY" clause would do the trick for you, something similar to:
SELECT * FROM table_name ORDER BY year DESC
Then, use your scripting language to display the data, a good idea could be (maybe) to fetch the year of the first row, store it in a temporal variable, then loop through the rows and check if the year has changed, if it has, change the value of the aforementioned variable, something like this:
$current_year = $data_set[0]['year'];
foreach ( $data_set as $data_row )
{
$current_year = ( $data_row['year'] != $current_year) ? $data_row['year'] : $current_year;
//Do something with it and/or the rest of the data
}
Hope this was of any help.
Cheers.

Categories