First time poster so I hope you can help me with what I think is a simple task but can't figure out.
I have a table called exports which among other things has a year and value field. I currently have data for the years from 1992 to 2011.
What I want to be able to do is extract this data from the database and then calculate the year on year percentage difference and store the results in an array so the data can be passed to a view file.
For example: ((1993-1992)/1992)*100) then ((1994-1993)/1993)*100) then ((1995-1994)/1994)*100) etc etc.
I need it to be flexible so I can add future data. For example I will eventually add data for the year 2012.
I'm really stuck as how to progress this. Help would be greatly appreciated.
If I'm understanding that correctly, the solution wouldn't have to be that complicated. A simple SELECT query to fetch the year and value, which you could then go through using a loop in PHP and calculate the percentages. Something like this:
<?php
// Get all the data from the database.
$sql = "SELECT year, value FROM exports";
$stmt = $pdo->query($sql);
// An array to store the precentages.
$percentages = [];
// A variable to keep the value for the last year, to be
// used to calculate the percentage for the current year.
$lastValue = null;
foreach ($stmt as $row) {
// If there is no last value, the current year is the first one.
if ($lastValue == null) {
// The first year would always be 100%
$percentages[$row["year"]] = 1.0;
}
else {
// Store the percentage for the current year, based on the last year.
$percentages[$row["year"]] = (float)$row["value"] / $lastValue;
}
// Overwrite the last year value with the current year value
// to prepare for the next year.
$lastValue = (float)$row["value"];
}
The resulting array would look like this:
array (
[1992] = 1.0,
[1993] = 1.2,
[1994] = 0.95
... etc ...
)
Related
I have run into an issue where i am adding the point for a user with the previous point already stored in the table via laravel. Now I have an issue where i need to loop all the points of a specific user and I need to add in a new column for each entry the difference between the old previous point and the current point.
From the table i have first entry point is 1 , second entry point is 11, third is 21 and 4th is 22. Here what I need is, I need to loop all these data and for the first record i need to add the difference as 1 in new column and for second the difference between 1st and 2nd row are 10 and for 3rd the difference between 2nd and 3rd are again 10 and for 4th record th diff between the 3rd and 4th are 1.
Please someone provide me with a function which will help me to update new column with the difference in points based on previous and the current point
I assume you are using model
You can try this.
// $id is equal to user_id
function difference($id) {
// First get all your data
$data = YourModel::where('user_id', $id)->get();
// Loop all your data
foreach($data as $d) {
//get previous data
$last = YourModel::where('user_id',$id)->where('created_at', '<', $d->created_at)->first();
// if null then return zero else get the point
$last = isset($last) ? $last->points : 0;
// get the difference from the last
$dif = $d->points - $last;
// putting the difference to the data
$d->difference = $dif;
$d->save();
}
}
Hope this will help you...
Sorry, I couldn't explain it more in the title but here's the deal.
I have a SQL table with items which have a classic date column where I ordered them by date in the loop. Now I want to add an echo into an existing loop to display a row in the looped table which will show Items added today, Items added yesterday and so forth.
This is how I'd like it to look when looped. (The closest I got was it looped by every second and added echoed part per every item which was a total mess)
PS: Reading on google maybe it should be included as usort with if inside existing foreach?
----------------------------
Table
----------------------------
echoed `<tr><td>Added: today<td></tr>`
---------------------------
Item 1
Item 2
Item 3
---------------------------
echoed `<tr><td>Added: yesterday<td></tr>`
---------------------------
Item 4
Item 5
Item 6
Item 7
---------------------------
echoed `<tr><td>Added: 29 Aug<td></tr>`
---------------------------
Item 9
Item 10
Item 11
etc
Edit: Date format doesn't have to be 29 Aug. It's just for the reference I'll tweak it myself. I just need a help with the logic of how to implement this.
you should sort them first in the database!
then when looping through the items you essentially remember which section you last displayed, and before outputting the first row of a new section, you output the section title instead:
$current = null;
foreach($rows as $row) {
$display = date_create($row['timestamp'])->format('Ymd'); // or whatever!
// it must consistently return something that makes the following consistent:
if($display != $current) {
// add separator that contains "today" or "yesterday" or the date
echo '<tr><td>'.$display.'</td></tr>';
$current = $display;
}
// display the actual row here
}
the problem gets harder, if you want to also show separator rows for dates that don't exist in database. then, you would have to create a date object first, and subtract one day at a time until the date matches the rows date, outputting separators accordingly.
update: special displays (please note, that $today and $yesterday must be simple types like string or int or something for this to work):
// before the loop!
$today = date_create()->format('Ymd');
$yesterday = date_create("-1 day")->format('Ymd');
$replacements = [
$today => 'today', // or whatever
$yesterday => 'yesterday', // or whatever
];
in the loop when echoing the $display:
echo '<tr><td>'.($replacements[$display] ?? $display).'</td></tr>';
this will look, if the formatted date should be replaced.
You have mentioned that you have already got the data sorted on the basis of days i.e. the field "added".
What you can do next is to loop through the retrieved result set. This is how you can proceed.
$dtPrevDate = null;
The above variable is going to be useful for the purpose of comparison of the dates i.e. "added".
Now loop through the retrieved data:
foreach($data as $datum){
if($dtPrevDate == $datum['added']){
// Keep printing item
}
else{
echo "Item added on: $datum['added']";
}
$dtPrevDate = $datum['added'];
}
The essence of the above code is dependent on the sorting that you have already managed to do using MySQL.
I'v got this array:
$by_date = array(
"2018-10-05"=>54,
"2018-10-07"=>20,
"2018-10-08"=>31,
"2018-10-12"=>52
);
I want to get value by date, but if the date doesn't exist get the lowest date value
for example:
if the date is "2018-10-07" I'll get 20
and if the date is "2018-10-10" I'll get 31
that can go to bigger differences between the date and the last key in the array
For example, if the date is "2019-01-25" I'll get 52 because "2018-10-12" is the last key in the array.
Thanks for the help :)
You guys where right the previews answer wasn't good enough
I'v made a work around that works for me, not sure about efficiency
if (!isset($by_date[$testVal])){
$by_date[$testVal] = null;
ksort($by_date);
$date_key = array_search($price_date,array_keys($by_date));
$by_date[$testVal] = (array_values($by_date)[$date_key-1]);
}
$by_date_price = $by_date[$testVal];
Thank you for the help and comments
You can do it with a simple if condition that uses isset() to check for your input as a key on the array. If the condition is met, you return the matched value, otherwise, use max() and array_keys() to return the value with the highest key.
$by_date = array(
"2018-10-05"=>54,
"2018-10-07"=>20,
"2018-10-08"=>31,
"2018-10-12"=>52
);
$testVal = '2018-10-12'
if (isset($by_date[$testVal]))
return $by_date[$testVal];
else
return $by_date[max(array_keys($by_date))];
I am having the worst time trying to get this to work. In the following code, I am gathering data from a database query and trying to build a muti-dimensional array object that will keep totals and tally up some information in a specific way. The problem is that instead of getting a value that is incrementing as it should, the value seems to be suffering from the last value it was assigned problem. Here is the code:
$REVIEWS = array();
$USER_REVIEWS = array();
$USER_IMGREVS = array();
pseudo-code: loop here which iterates over the DB results creating
$date - which is into this function as its called for each day of month
$p1user - which is one of the users (there are 3) 'levels' of users
$hr - is the hour which is built from the transaction's timestamp
$hr = date('H', $row['P1TIMESTAMP']);
$p1user = $row['P1USER'];
$REVIEWS[$date] += 1;
$USER_REVIEWS[$date][$p1user][$hr] += 1;
$USER_IMGREVS[$date][$p1user][$hr] += $row['F5'];
print "PASS1<br/>\n";
print "Value of Total Reviews: [".$REVIEWS[$date]."]<br/>\n";
print "Value of User Reviews: [".$USER_REVIEWS[$date][$p1user][$hr]."]<br/>\n";
print "Value of Reviewed Images: [".$USER_IMGREVS[$date][$p1user][$hr]."]<br/>\n";
print "<br/><br/>\n";
So - the 'total reviews' increments by one, as it should, for each time i print this. SO far so good. The next two arrays will only print the last values they were assigned, and will not be added together like they should. Why not? I have attempted to do this another way by literally creating the arrays one by one and assigning them in whole to the array containing them - but that also does not seem to work. Any insights?
i don't know how you initilize your array, maybe this will help:
// replace this 2 lines:
$USER_REVIEWS[$date][$p1user][$hr] += 1;
$USER_IMGREVS[$date][$p1user][$hr] += $row['F5'];
// with this code:
if (!isset($USER_REVIEWS[$date]))
$USER_REVIEWS[$date] = array();
if (!isset($USER_REVIEWS[$date][$p1user]))
$USER_REVIEWS[$date][$p1user] = array();
if (!isset($USER_REVIEWS[$date][$p1user][$hr]))
$USER_REVIEWS[$date][$p1user][$hr] = 0;
$USER_REVIEWS[$date][$p1user][$hr] += 1;
if (!isset($USER_IMGREVS[$date]))
$USER_IMGREVS[$date] = array();
if (!isset($USER_IMGREVS[$date][$p1user]))
$USER_IMGREVS[$date][$p1user] = array();
if (!isset($USER_IMGREVS[$date][$p1user][$hr]))
$USER_IMGREVS[$date][$p1user][$hr] = 0;
$USER_IMGREVS[$date][$p1user][$hr] += $row['F5'];
Sir, I dont understand very well why your coed is not working, but in my first test, I would change these lines:
$count = 1;
$USER_REVIEWS[$count][$p1user][$hr] += 1;
$USER_IMGREVS[$count][$p1user][$hr] += $row['F5'];
$count++;
Please, check if this code helps you anyway.
Your print statements for those values rely on the value of $p1user:
print "Value of User Reviews: [".$USER_REVIEWS[$date][$p1user][$hr]."]<br/>\n";
print "Value of Reviewed Images: [".$USER_IMGREVS[$date][$p1user][$hr]."]<br/>\n";
If you want to print it for all users you should loop over all possible users rather than just using $p1user. Either that or add them up if you want their sum.
Edit: Something that was bugging me was your data structure. It doesn't seem to represent your data very well. In your loop why don't you build up useful information that you store at the base of the review array?
I've created a database and stored some data along with the scheduled date for each item. I would like to output a schedule in the format like this:
January 1:
- 1:00 pm
Doctors
Appt -
4:45 pm
Birthday
Party January 3:
- 10:00 am
Hair Cut
Appt -
4:50 pm
Bob's House
The problem I've run into is I'm not sure on how to output the data like this. I only want to display the date once but the time and date are in the same row, so a foreach loop won't work. If there's a better way to structure my data to achieve this then I'm willing to do that also.
My Table contains the following data for each row:
id, name, about, date, time
Any help would be much appreciated. Thanks
You don't need to structure your data differently, it sounds like it's been normalised properly. Instead pre-process your data into a temporary array that groups results by date, then loop over that:
$dateArray = array();
foreach($dbResult as $result) {
$dateArray[$result['date']][] = $result;
}
foreach($dateArray as $date => $entries) {
echo $date . ':<br>';
foreach($entries as $entry) {
echo $entry['time'] . '<br>' . $entry['name'];
}
}
Avoid doing two queries because you can do what you need with one and it'll put your database under less load.
Personally I would consider structuring the database as such:
Table: Dates(DateId, Date)
Table: Times(TimeDateID, DateID, Time)
Table: Appointment(AppointmentID, Name)
Table: Appointment_Time(AppointmentID, TimeDateID)
That way you could loop through all your dates, for each date loop through all the times that have that DateID, then loop through all your appointment_times with that timedateID
Pull the data and then create a multidimensional array from it, e.g.:
$data = array(
'January 3' => array (
'1:00 PM' => array (
'Doctor\'s Appt'
),
'4:45 pm' => array (
'Birthday Party',
'Something else at 4:45 as well'
)
)
);
(Your dates and times will probably not be those strings, but you get the idea.)
Then loop through dates and times in a natural way.
To create an indexed data structure like that shown above:
foreach ($dbResult as $row){
$data[$row['date']][$row['time']] = $row;
}
You can run a query which selects data for a given date. First, run a query which will give you a list of dates... something like this:
SELECT DISTINCT date FROM table;
Then do a foreach loop on the resulting list, running this query inside the loop:
SELECT time, name, about FROM table WHERE date = currentdate;
This will give you a list of the items for the current date, and you can simply iterate over them. It shouldn't be a performance problem if this is a single-user application or low-load web application.
If you prefer only one query, try this:
SELECT date, time, name, about FROM table ORDER BY date ASC, time ASC
You can then use a single foreach and a placeholder variable to loop over this, without the semantic hoop-jumping of multiple associative arrays and the like. Set the initial value of the placeholder value to the first date in the array, and then check on each loop to see if the date has changed. If it has, output a date header before you output the time, name, and notes about each entry, set the placeholder to the new date, and repeat.