Currently we store hours in a table that has a percentage field to distribute data across the week.
eg.
| dayint | daytext | hours | percent |
+--------+---------+-------+---------+
| 1 | mon | 9 | 0.14 |
| 2 | tue | 15 | 0.23 |
| 3 | wed | 9 | 0.14 |
| 4 | thu | 9 | 0.14 |
| 5 | fri | 0 | 0.00 |
| 6 | sat | 23 | 0.35 |
We are now adding a monthly distribution as well as weekly, so to calculate this I am:
Getting number of weeks in a month.
$weeks = $days_in_month/7
Iterating through each day's percent and dividing it by number of weeks.
$percent = $day['percent'] / $weeks
If my assumption is correct, this should distribute data across the month evenly. The problem is that it is consistently about 1ish % extra for the month.
If I enter 1000, I get 1013. If I enter 200, I get 202. Maybe I am just going about it wrong mathematically, any help is appreciated.
If your percent column stores data that has been rounded and is used in your monthly calculation as opposed to displaying rounded results that are stored accurately elsewhere then you will get rounding errors.
The example below shows the results for three weeks and the tables afterwards show the results using the actual data and the rounded data.
|Hours|Actual |Rounded| |Hours|Actual |Rounded| |Hours|Actual |Rounded|
| 9|0.13846153846154| 0.14| | 10|0.15625000| 0.16| | 8|0.135593220339| 0.14|
| 15|0.23076923076923| 0.23| | 14|0.21875000| 0.22| | 13|0.220338983051| 0.22|
| 9|0.13846153846154| 0.14| | 8|0.12500000| 0.13| | 11|0.186440677966| 0.19|
| 9|0.13846153846154| 0.14| | 10|0.15625000| 0.16| | 7|0.118644067797| 0.12|
| 0|0.00000000000000| 0| | 1|0.01562500| 0.02| | 2|0.033898305085| 0.03|
| 23|0.35384615384615| 0.35| | 21|0.32812500| 0.33| | 18|0.305084745763| 0.31|
| 65|1.00000000000000| 1.00| | 64|1.00000000| 1.02| | 59|1.000000000000| 1.01|
Over the three weeks iterating with
$percent = $day['percent'] / $weeks
actual column gives the results
0.14343
0.22329
0.14997
0.13779
0.01651
0.32902
1.00000
whereas rounded column gives
0.146666667
0.223333333
0.153333333
0.14
0.016666667
0.33
1.01
Remember rounded results always go up or stay the same never downwards, so the error will always be slightly more than you expect.
I decided to change my approach and go about it like this:
Get the total hours for the month by looping through:
$total = $total + $day['hours'];
Use the stored hours instead of the percent to calculate a new percent using:
$percent = $v['hours']/$total;
This approach returns the correct data.
Related
I need to get past 30 days sales records from MYSQL database to display in a bar chart how many items sold each day. Also I need to display past 30 days in my chart x axis in my php document. I tried run this code inside a for loop. because I am running some other codes to display some data using this loop. Take a look at the following code and help me how to achieve this.
This is the table I try to get data from
Date format (YYYY-MM-DD)
Products Table
product_id | sold_by | qty | added_date | sold_date
-----------+---------+-----+-------------+-----------
3 | 12 | 7 | 2022-05-05 | 2022-07-28
3 | 12 | 7 | 2022-05-05 | 2022-07-29
3 | 12 | 7 | 2022-05-05 | 2022-07-30
3 | 12 | 1 | 2022-05-05 | 2022-07-30
3 | 12 | 2 | 2022-05-05 | 2022-07-30
6 | 22 | 4 | 2022-06-06 | 2022-07-31
8 | 11 | 6 | 2022-08-05 | 2022-07-31
Deleted Table
product_id | added_date | delete_date
-----------+-------------+-----------
3 | 2022-05-05 | 2022-07-28
3 | 2022-05-05 | 2022-07-29
3 | 2022-05-05 | 2022-07-30
3 | 2022-05-05 | 2022-07-30
3 | 2022-05-05 | 2022-07-30
6 | 2022-06-06 | 2022-07-31
8 | 2022-08-05 | 2022-07-31
As you can see for some days I have multiple records.
<?php
//for loop to run 30 times to get 30 days results
for ($i = 30; $i >= 0; $i--) {
$sold_products_count = mysqli_num_rows(mysqli_query($conn, "SELECT * FROM products WHERE sold_date = CURRENT_DATE - $i"));
$deleted_count = mysqli_num_rows(mysqli_query($conn, "SELECT * FROM deleted WHERE delete_date = CURRENT_DATE - $i"));
?>
{
<?php
$current_date = date("Y-m-d");
$new_date = date_create($current_date);
date_sub($new_date, date_interval_create_from_date_string("$i day"));
?>
x: '<?php echo date_format($new_date, "Y-m-d"); ?>',
a: <?php echo $deleted_count; ?>,
s: <?php echo $sold_products_count; ?>,
},
<?php
}
?>
x- X axis data in the chart
a - number of products deleted in specific date
s - number of products sold in specific date
With the above code I was able to print the x axis data. I am not sure how to get past 30 days data from the SQL database. I think the problem is in the $i part in the SQL query.
In your query, if you use INTERVAL, you can use some days for adding/reducing from the current or specific date.
For example in your case, if you always want to get the last 30 days data, you can use your WHERE like this:
sold_date >= CURDATE() - INTERVAL 30 DAY
I have a weight calculated, and a database table that contains the range of amounts, now I want to check if the calculated weight is between the ranges in my table.
Shipping Fee Table
--------------------------------------------------
id | weight_from | weight_to | amount |
----+---------------+--------------+--------------
1 | 0.5 | 100 | 100 |
2 | 500 | 1000 | 120 |
3 | 1000 | 3000 | 180 |
For example the calculated weight is 505kg it will find it on the table if it's between weight_from & weight_to
I found something like this, but it is not like what I'm trying to do, because it pass a number, and not getting the value of database table.
Code
$fee = Fee::whereBetween('column', [1, 150])->first();
you can use > and < with two where condition
$fee = Fee::where('weight_from', '>=', 500)->where('weight_to', '<=', 500)->first();
EXPLAIN
Let's say we have this transaction table :
+----+-------------+--------+----------------+----------------+---------------------+
| id | id_customer | amount | id_where_trans | id_money_from | date_trans |
+----+-------------+--------+----------------+----------------+---------------------+
| 1 | 10 | 10 | 100 | NULL | 2015-07-20 10:20:30 |
| 2 | 10 | -2 | 100 | NULL | 2015-07-21 09:10:11 |
| 3 | 10 | 7 | 120 | NULL | 2015-07-24 18:22:25 |
| 4 | 10 | -11 | 120 | here the magic | 2015-07-24 18:22:26 |
+----+-------------+--------+----------------+----------------+---------------------+
Read this in "human" language:
id 1 => Customer Alessandro (id_customer 10) charge 10€ on his account in shop A (id_where trans = 100)
id 2 => Customer Alessandro spent 2€ on Shop A
id 3 => Customer Alessandro charge 7€ on his account in shop B
id 4 => Customer ALessandro spend 11€ in shop B.
At the end of period (month, for example), Shop B need to receive 8€ (+10-2) from another shop, in our example shop A.
/end of human read.
You imagine that insert is a simple (for id 4, for example):
INSERT INTO transaction (id_customer, amount, id_where_trans, date) VALUES (10,-11,120,2015-07-24 18:22:26)
GOAL
My goal is set - during the insert, and if possible / simpler via PHP - the SQL splitted in two or more SELECT:
INSERT INTO transaction (id_customer, amount, id_where_trans, id_money_from, date) VALUES (10,-8,120,100,2015-07-24 18:22:26)
INSERT INTO transaction (id_customer, amount, id_where_trans, id_money_from, date) VALUES (10,-3,120,NULL,2015-07-24 18:22:27)
+----+-------------+--------+----------------+------------+---------------------+
| id | id_customer | amount | id_where_trans | id_money_from | date |
+----+-------------+--------+----------------+------------+---------------------+
| 1 | 10 | 10 | 100 | NULL | 2015-07-20 10:20:30 |
| 2 | 10 | -2 | 100 | NULL | 2015-07-21 09:10:11 |
| 3 | 10 | 7 | 120 | NULL | 2015-07-24 18:22:25 |
| 4 | 10 | -8 | 120 | 100 | 2015-07-24 18:22:26 |
| 5 | 10 | -3 | 120 | NULL | 2015-07-24 18:22:27 |
+----+-------------+--------+----------------+------------+---------------------+
If I can get a table with that informations, I can run a query that make my final job correctly.
Basically, I need to calculate the id_shop where money are taken for discharge (in this case, -8 from 100, that made previous charge, and so is NOT NULL, and -3 from 120,itself, THIS IS NULL).
Please note that FIRST I consume / discharge the previous charge (id 4 now has id_money_from 100), AFTER I will consume / discharge others amounts (id 5 in effect is NULL, because that -3 has taken from id 3)
ASSUMPTION / MANDATARY
1) id are INCREMENTAL, no concurrency. Date are INCREMENTAL, date of id 4 is >= of id 3 and so on.
2) If amount of last recharge is made from same id where transaction is done (see id 1 and id 2) insert NULL (I need mandatary NULL)
3) First charge made, first need to be zero-ed, and so on.
MY LOGIC / PSEUDOCODE
1) If a transaction is negative, make a recursive getting LAST positive charge which, summed to the negative susequential, is not zero.
getted this charge, if id_where_trans==id_money_from we need insert, simply insert, with NULL
INSERT INTO transaction (id_customer, amount, id_where_trans, id_money_from, date) VALUES (10,-2,120,NULL,2015-07-24 18:22:26)
Recursive start here
If this amount is <= of last recharge, walking in database and split negative in two or more id_where_trans (problaby in real scenario this will be impossible, but I need to think that amount from discharge (id_money_from) could be splitted by 2, 3, x id_where_trans). For example, if SHOP A charge +1, Shop B charge +1, Shop C charge +1 and SHOP D DISCHARGE -3, we need to insert 3 different rows.
$amount_to_discharge = x;
$last_positive = $query->("SELECT * FROM transaction WHERE "); // make the SUB-SUM
if ($last_positive['amount'] >= $amount_to_discharge) {
$query->("INSERT INTO......");
} else {
// start recursive
$sql = "SELECT * FROM AMOUNT WHERE amount > 0 AND id < $last_positive['id']";
$new_search = $query->sql($sql);
// how implement correctly that recursive?
}
Thank you guy. Let me know if you need others explain!
I am working on a script for a drivers license website, and I need to make a calendar like table for the students, so they can see when they have which lesson.
Right now we are updating the table manually, but I would like to make a script so it can do it automatically.
The table looks like this: (By the way, its a HTML table).
+----------+--------+---------+-----------+----------+--------+
| Week Nr. | Monday | Tuesday | Wednesday | Thursday | Friday |
+----------+--------+---------+-----------+----------+--------+
| 17 | 14 | 1 | 16 | 2 | |
+----------+--------+---------+-----------+----------+--------+
| 18 | 4 | 1 | 6 | | |
+----------+--------+---------+-----------+----------+--------+
| 19 | 8 | 1 | 11 | | |
+----------+--------+---------+-----------+----------+--------+
| 20 | 14 | 1 | 16 | 2 | |
+----------+--------+---------+-----------+----------+--------+
Lets say its this week (Week 17), it has its own set of lessons for every day, except Friday, which is the same for every week. Then it is the week after, which has its own set of lessons, and then it is 3 weeks after, which again has its own set of lessons. Then the 4th week, it start all over, with the same set as week 17, because its a 3 week program, over and over again.
What i want to do is that it automatically updates the table, so it shows the current week number. Then let us say that it is next week now, the table should have automatically update it self to show the current week and its set of lesson numbers.
The numbers under the column "Week Nr." are the week numbers, and the numbers under the day names are the lesson numbers.
So next week it should look like this:
+----------+--------+---------+-----------+----------+--------+
| Week Nr. | Monday | Tuesday | Wednesday | Thursday | Friday |
+----------+--------+---------+-----------+----------+--------+
| 18 | 4 | 1 | 6 | | |
+----------+--------+---------+-----------+----------+--------+
| 19 | 8 | 1 | 11 | | |
+----------+--------+---------+-----------+----------+--------+
| 20 | 14 | 1 | 16 | 2 | |
+----------+--------+---------+-----------+----------+--------+
| 21 | 4 | 1 | 6 | | |
+----------+--------+---------+-----------+----------+--------+
Is there anybody who could give me a hint on how to do that with PHP. I have tried everything I knkw, but I just cant get it right.
This is not exactly what you want, but it could be a good starting point. Just modify it to print out the HTML tags.
//Set a counter for the lessons
$j = 0;
//Loop through the weeks of the year
for ($i = 1; $i <= 52; $i++) {
echo "Week: ".$i."<br>";
echo "This weeks lessons: " . $j."<br>";
//Incrase counter
$j++;
if ($j % 3 === 0) {
//Reset counter if need
echo "<hr>";
$j = 0;
}
}
Started learning PHP and MySQL yesterday and have managed to create two tables, insert rows and then display that data on a web page using various different groupings. Now I need to do a calculation based on data in the two tables and write the result back to one of the tables.
I'm trying to figure out how to perform an equation for a row with a date in table A using a range of values associated with a range of dates in table B. The two dates are in the format YYYY-MM-DD, but the days mostly do not match, so I need match on the month.
Here's the two tables I have:
Table A (user)
+----+----------+------------+-------------+
| id | username | start-date | bench-value |
+----+----------+------------+-------------+
| 1 | tim | 2010-03-04 | |
+----+----------+------------+-------------+
| 2 | jim | 2010-05-30 | |
+----+----------+------------+-------------+
| 3 | fred | 2010-06-12 | |
+----+----------+------------+-------------+
| 4 | sam | 2010-08-16 | |
+----+----------+------------+-------------+
| 5 | jane | 2010-10-21 | |
+----+----------+------------+-------------+
| 6 | ella | 2010-10-21 | |
+----+----------+------------+-------------+
| 7 | bob | 2011-01-24 | |
+----+----------+------------+-------------+
Table B (benchmark)
+----+------------+---------+
| id | start-date | value |
+----+------------+---------+
| 1 | 2010-01-31 | 1173.19 |
+----+------------+---------+
| 2 | 2010-02-28 | 1199.85 |
+----+------------+---------+
| 3 | 2010-03-31 | 1264.91 |
+----+------------+---------+
| 4 | 2010-04-30 | 1263.43 |
+----+------------+---------+
| 5 | 2010-05-31 | 1211.36 |
+----+------------+---------+
| 6 | 2010-06-30 | 1187.32 |
+----+------------+---------+
| 7 | 2010-07-31 | 1218.30 |
+----+------------+---------+
| 8 | 2010-08-31 | 1207.96 |
+----+------------+---------+
| 9 | 2010-09-30 | 1272.12 |
+----+------------+---------+
| 10 | 2010-10-31 | 1280.27 |
+----+------------+---------+
| 11 | 2010-11-30 | 1275.60 |
+----+------------+---------+
| 12 | 2010-12-31 | 1346.45 |
+----+------------+---------+
| 13 | 2011-01-31 | 1337.07 |
+----+------------+---------+
| 14 | 2011-02-28 | 1338.37 |
+----+------------+---------+
| 15 | 2011-03-31 | 1349.14 |
+----+------------+---------+
And here's an example of what I'm trying to achieve:
tim's current bench value today = the sum of: (first(benchmark.value)/latest(benchmark.value))for every month from the first to the latest month inclusive
First date = 2010-03 which is id 3 = 1264.91
Latest date = 2011-03 which is id 15 = 1349.14 (this is always the last row as I am trying to calculate on "today" and nothing in the future)
1/(first/latest) =1/(1264.91/1349.14) = 1.0666 [this is bench.id=3]
...now iterate...
1/(next/latest) =1/(1263.43/1349.14) = 1.0678 [bench.id=4]
1/(next/latest) =1/(1211.36/1349.14) = 1.1137 [bench.id=5]
1/(next/latest) =1/(1187.32/1349.14) = 1.1363 [bench.id=6]
1/(next/latest) =1/(1218.30/1349.14) = 1.1074 [bench.id=7]
1/(next/latest) =1/(1207.96/1349.14) = 1.1169 [bench.id=8]
1/(next/latest) =1/(1272.12/1349.14) = 1.0605 [bench.id=9]
1/(next/latest) =1/(1280.27/1349.14) = 1.0538 [bench.id=10]
1/(next/latest) =1/(1275.60/1349.14) = 1.0577 [bench.id=11]
1/(next/latest) =1/(1346.45/1349.14) = 1.0020 [bench.id=12]
1/(next/latest) =1/(1337.07/1349.14) = 1.0090 [bench.id=13]
1/(next/latest) =1/(1338.37/1349.14) = 1.0080 [bench.id=14]
...and finish up...
1/(current/latest) =1/(1349.14/1349.14) = 1.0000 [bench.id=15]
Total = 13.7997 = 1.0666 + 1.0678 + 1.1137 + 1.1363 + 1.1074 + 1.1169 + 1.0605 + 1.0538 + 1.0577 + 1.002 + 1.009 + 1.008 + 1
So I would then want to write that result back to Table A, giving me:
Table A (user)
+----+----------+------------+-------------+
| id | username | start-date | bench-value |
+----+----------+------------+-------------+
| 1 | tim | 2010-03-04 | 13.7997 |
+----+----------+------------+-------------+
As this is an iterative process it would be a much shorter calculation for a user like 'bob' who started in 2011-01.
I would also like to be able to do this every 4 months to produce termly stats so that someone like user tim would be calculated like this (the initial search to find the first date would need to take into account over a 4 month period):
1/(first/latest) = 2010-03 = 1/(1264.91/1349.14) = 1.0666
1/(next/latest) = 2010-07 = 1/(1218.30/1349.14) = 1.1074
1/(next/latest) = 2010-11 = 1/(1275.60/1349.14) = 1.0577
1/(current/latest) = 2011-03 = 1/(1349.14/1349.14) = 1.0000
Total = 1.0666 + 1.1074 + 1.0577 + 1 = 4.2317
That major issues I'm having are two fold:
1. how to use the user.start-date value for each user to pick the first(benchmark.value) based ont he year and the month (day is unimportant).
2. how to iteratively calculate the formula up to and including the latest value in the bench table - at the end of april, a new row with id=16 would be added and if this were run then the April value would become the last value used in the calculation.
As I'm learning SQL And PHP right now I'm not sure which parts of this process should be done in SQL and which in PHP.
Any and all help would be greatly appreciated as I'm determined to figure this out.
That major issues I'm having are two fold:
how to use the user.start-date value
for each user to pick the
first(benchmark.value) based on the
year and the month (day is
unimportant).
how to iteratively calculate the
formula up to and including the
latest value in the bench table - at
the end of april, a new row with
id=16 would be added and if this
were run then the April value would
become the last value used in the
calculation.
As I'm learning SQL And PHP right now I'm not sure which parts of this process should be done in SQL and which in PHP.
Any and all help would be greatly appreciated as I'm determined to figure this out.
Just for reference, I've been reading:
http://dev.mysql.com/doc/refman/5.1/en/date-and-time-functions.html
http://www.databasejournal.com/features/mssql/article.php/10894_2191631_3/Working-with-SQL-Server-DateTime-Variables.htm
There were more but it won't let me post the other links yet...
There's almost too much info out there, so some guided advice would be realy appreciated. Thanks again.
I wouldn't include the column bench-value in table A. This value will be constantly changing, so it would be better to create a View that would calculate the latest User bench-value or create a stored procedure that takes a User as a parameter and then returns the bench-value
There also needs to be a link/key between the two tables, right now there is no way to tell which user is related to which benchmark
Wow, what a well asked question. Sadly my reply maybe a lot shorter.
What I think you're looking for is:
bob's current bench value today = the
sum of:
first(benchmark.value)/latest(benchmark.value)
First date = 2011-01 which is id 13 =
1337.07 Latest date = 2011-03 which is id 15 = 1349.14
select username, start_date, tmp.value/tmp2.value as new_mark from tablea
join (select id,value from tableb having id=min(id) group by id) as tmp
on tablea.id=tmp.id
join (select id,value from tableb having id=max(id) group by id) as tmp2
on tablea.id=tmp2.id
That seems ugly but should work.