Replace zero with last valid value Mysql - php

i'm using mysql to store Kwh usage of my home. I get a fault rarely and get a 0 value to get stored. When i extract the values from my table i don't want to get that 0s but the last valid value before.
SELECT unix_timestamp(dataora) as time, kwhg
FROM misure
WHERE dataora BETWEEN '2013-10-08 00:00:00.000' AND '$data_scelta 23:59:59.997'
GROUP BY date(dataora),hour(dataora)
I used the above code to get the below table:
+-------+-----------+
| time | kwhg |
+-------+-----------+
| 9 | 2 |
| 10 | 3 |
| 11 | 0 |
| 12 | 4 |
| 13 | 0 |
+-------+-----------+`
I want to obtain
+--------+----------+
| time | kwhg |
+-------+-----------+
| 9 | 2 |
| 10 | 3 |
| 11 | 3 |
| 12 | 4 |
| 13 | 4 |
+-------+-----------+`
and remove the zero with the previus value.
Any tricks to do that?

You can use MySQL user-defined variables to return either the current row's value of kwhg if it's greater than zero, or else the variable defined on the previous row.
SELECT unix_timestamp(dataora) as time, #kwhg := IF(kwhg>0, kwhg, #kwhg) AS kwhg
FROM misure
WHERE dataora BETWEEN '2013-10-08 00:00:00.000' AND '$data_scelta 23:59:59.997'
GROUP BY date(dataora),hour(dataora)
Like #OddEssay's answer, this can't come up with a nonzero value if the first entry is zero. In that case, it will return whatever the current value of #kwhg is, which is probably NULL unless you've run the query before in the current session.

If it's a small result set, you could simply loop over it and created a fixed dataset with something like:
$fixedResults = array();
$lastGoodReading = 0;
foreach($results as $row){
if($row['kwhg']){
$fixedResults[$row['time']] = $row['kwhg'];
$lastGoodReading = $row['kwhg'];
} else {
$fixedResults[$row['time']] = $lastGoodReading;
}
}
Which will work if there is multiple failed readings in a row, but will still give zero if the first result fails.
You might also want to do something a bit more advanced, like checking both the previous result, and the next result and take an average of the two.

in mysql
UPDATE mytable
SET kwhg = (#n := COALESCE(number, #n))
ORDER BY time;
#n is a MySQL user variable

Related

Querying MySQL results into multi-dimensional associative PHP array

I'm probably overlooking a fairly simple way of doing this; perhaps someone has an idea of how to make this easy with limited looping and without an excessively long query. Let's say I have a MySQL table with data like this: (There's 12 months, and could be maybe 10 different possible grades). I'll query out just the results for a given user_id and year.
+----+---------+------+-------+-------+-------+
| id | user_id | year | month | grade | value |
+----+---------+------+-------+-------+-------+
| 1 | 1 | 2021 | Jan | A | 95 |
+----+---------+------+-------+-------+-------+
| 2 | 2 | 2021 | Jan | D | 75 |
+----+---------+------+-------+-------+-------+
| 3 | 2 | 2021 | Feb | F | 45 |
+----+---------+------+-------+-------+-------+
I want to be able to query the data and put it into a multi-dimensional associative PHP array.
Essentially, so I can access the data like this:
echo $month_value['Jan']['D']; // Should give me 75
echo $month_value['Feb']['F']; // Should give me 45
Figured out a simple method that works for me:
$sql_retrieve = $con->prepare("SELECT month, grade, value
FROM table
WHERE user_id = ? AND year = ?;");
$bind_process = $sql_retrieve->bind_param('ii',$user_id,$year);
$sql_retrieve->execute();
$result = $sql_retrieve->get_result();
$month_values = []; // initialize array
if($result->num_rows > 0 ){ // If there are results
while($row=$result->fetch_assoc()){
$month_values[$row["month"]][$row["grade"]] = $row["value"]; // add to array
} // end while
} // end of if num_rows > 0
print_r($month_values); // Example
echo 'Value: '.$month_values['Jan']['D'];
This then provides the MySQL results into a multi-dimensional associative PHP array, so they can be referenced as such.

Getting only one result for a "football matchup" per team per week

I'm putting together a new project, and one of the things I need to do is get the results of a Fake Football (American) match. I'm doing this in php and mysql, utilizing CodeIgniter as my framework. My dbfiddle is as follows:
https://www.db-fiddle.com/f/5Q7QezddpNEGabaia2w5FQ/0
Now, as you can see, each team has an entry for home_team_id and away_team_id. What I would like to do is have a query that gets only ONE result for each team (regardless if they are home or away). I'd rather not programmatically process this data if I don't have to.
The results should be something along the lines of the following:
SELECT week, home_team_id, away_team_id,
my_score, their_score,
a.team_name as home_team, b.team_name as away_team
FROM nfl_user_matchups nm
LEFT JOIN user_teams a ON nm.home_team_id = a.user_teams_id
LEFT JOIN user_teams b ON nm.away_team_id = b.user_teams_id
WHERE week = 1
Expected Final Data would be something like this (my_score would be home_team_id score, their_score would be away_team_id score):
+------+--------------+--------------+----------+-------------+
| week | home_team_id | away_team_id | my_score | their_score |
+------+--------------+--------------+----------+-------------+
| 1 | 3 | 9 | 112 | 144 |
+------+--------------+--------------+----------+-------------+
| 1 | 7 | 2 | 85 | 96 |
+------+--------------+--------------+----------+-------------+
| 1 | 1 | 6 | 111 | 114 |
+------+--------------+--------------+----------+-------------+
| 1 | 4 | 5 | 99 | 125 |
+------+--------------+--------------+----------+-------------+
| 1 | 8 | 10 | 140 | 122 |
+------+--------------+--------------+----------+-------------+
Your problem statement basically means that a pair of teams competing, viz., (1,2) are to be treated same as (2,1). One way to handle such requirements is to ensure that for any match between these two teams, we ensure that they are in the same order. So, basically we get the Least() team id value out of the two teams, and always put it in the first index; and the Greatest() value always at the second (last) index. It is noteworthy that Greatest() is not same as Max(). Max() function computes maximum on a column; while Greatest() is generally used to compare values across a row.
Now, we can simply GROUP BY on this pair and compute the aggregates as desired. While determining home/away scores, you will need to use CASE .. WHEN expression to determine whether a particular row has home id the least, or away id:
SELECT
week,
LEAST(home_team_id, away_team_id) AS home_id,
GREATEST(home_team_id, away_team_id) AS away_id,
MAX(CASE
WHEN LEAST(home_team_id, away_team_id) = home_team_id
THEN my_score
ELSE their_score
END) AS home_score,
MAX(CASE
WHEN GREATEST(home_team_id, away_team_id) = away_team_id
THEN their_score
ELSE my_score
END) AS away_score
FROM nfl_user_matchups
WHERE week = 1
GROUP BY
week,
home_id,
away_id;
View on DB Fiddle

Updating the table with new value by finding specific row

I have a table that I add information depending on the order number.
So when I enter information, I add some column names as numbers.
Then update the rows with new values.
My table takes 3 values everytime I insert value.
order number| total left | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9|
------------------------------------------------------------------------
11 | 100 | a | b | c | d | e | f | 0 | | |
------------------------------------------------------------------------
12 | 10 | x | y | z | 0 | | | s | d | f|
-------------------------------------------------------------------------
When I try to add new column, the value of the new rows in every other value becomes null or 0 depending on if it is int or varchar.
When I insert 3 values to order number 12, I want the last 0 in that row to be updated.
(In this case, 4-5-6 but I get 7-8-9 updated.)
So what is the best way for finding the last row which is 0
(in this case column 4 for order number 12 and insert the new values of s,d,f to the 4-5-6 instead of 7-8-9 ?
So maybe something like:
Loop through rows, find 0, insert 3 rows, break.
I take the last column:
$NewColumnNameKoliAdet=$LastColumnName+1;
$NewColumnNameMusteri=$LastColumnName+2;
$NewColumnNameTarih=$LastColumnName+3;
Then I add columns and update the table.
$Query="ALTER TABLE `koli_stok_hareketleri`
ADD `$NewColumnNameKoliAdet` INT(11) NOT NULL AFTER `$LastColumnName`,
ADD `$NewColumnNameMusteri` VARCHAR(100) NOT NULL AFTER `$NewColumnNameKoliAdet`,
ADD `$NewColumnNameTarih` VARCHAR(100) NOT NULL AFTER `$NewColumnNameMusteri`;";
$Query="UPDATE koli_stok_hareketleri SET kalan_koli=kalan_koli-
'$Uretilen_Koli',
`$NewColumnNameKoliAdet` = '$Uretilen_Koli',
`$NewColumnNameMusteri` = '$Musteri_ismifromrow',
`$NewColumnNameTarih` = '$Now'
WHERE koli_ismi ='$Koli_IsmifromRow' AND
koli_parti_no='$Parti_NofromRow'";
So the problem is it adds three value to each row automatically and but when I update, I need to update the order number 12 from 4th column not 7.

Sql – Insert value in first empty cell of column and show ID

I have an sql statement that will insert a value to the first empty cell. And if I ran the php script again, then it inserts into the next null cell etc.
Problem: I also want to find out the ID of that row, and value of another column in that row. In the Mysql table below, I want a value inserted in the first ‘null’ of COLUMN A, and also know the id and value in COLUMN B corresponding to that (ie id=3 and COLUMN B= 11).
My_TABLE
+---------+--------------+-------------+
| ID | COLUMN A | COLUMN B |
+---------+--------------+-------------+
| 1 | 6 | 78 |
| 2 | 7 | 90 |
| 3 | NULL | 11 |
| 4 | NULL | 5 |
| 5 | NULL | 123 |
+---------+--------------+-------------+
The following sql statement in PHP script will make it possible to insert value to the first empty cell in COLUMN A:
UPDATE My_TABLE
SET COLUMN A = 83
WHERE COLUMN A IS NULL
LIMIT 1;
Result will be:
+----+----------+------------+
| ID | COLUMN A | COLUMN B |
+----+----------+------------+
| 1 | 6 | 78 |
| 2 | 7 | 90 |
| 3 | 83 | 11 |
| 4 | NULL | 5 |
| 5 | NULL | 123 |
+----+----------+------------+
I also want to have an sql script that will print within PHP (echo) the values of ID and COLUMN B values corresponding to the first COLUMN A null value (ie ID= 3; COLUMN B= 11).
fetch the row by condition in this case you will have ID and COLUMN B
select *
from My_TABLE
where COLUMN A IS NULL
order by id
limit 1
Update by ID the selected row:
update My_TABLE
set COLUMN A = :SOME_VALUE
where ID = :ID_FROM_FETCH
Not sure if this case will fit what you are questioning.
mysqli_insert_id
From this function I'm pretty sure you will able to write the script for what you need.
Note* If it fits what you need, please read the warning as I'm not
sure if it will deprecated from the latest PHP version. Kindly take
note.

Get total views per day including leaving "0 views" for a day that has no record

I am creating a graph where I can get the total views everyday for a certain range, or as long it goes back.
The problem I am having is to fill a default number of 0 when no views has been made for a certain day, some days there may be absolutely no views in a day so I need MySQL to return a default of 0 when none is found - I have no idea how to do this.
This is the query I use to get the total views a day:
SELECT DATE(FROM_UNIXTIME(v.date)) AS date_views,
COUNT(v.view_id) AS total_views
FROM
(
views v
)
GROUP BY date_views
ORDER BY v.date DESC
My results return this:
+------------+-------------+
| date_views | total_views |
+------------+-------------+
| 2012-10-17 | 2 |
| 2012-10-15 | 5 |
| 2012-10-14 | 1 |
| 2012-10-10 | 7 |
+------------+-------------+
However there are missing days that I want to return 0 for it, as 2012-10-16, 2012-10-11, 2012-10-12, 2012-10-13 is not included.
So, for example:
+------------+-------------+
| date_views | total_views |
+------------+-------------+
| 2012-10-17 | 2 |
| 2012-10-16 | 0 |
| 2012-10-15 | 5 |
| 2012-10-14 | 1 |
| 2012-10-13 | 0 |
| 2012-10-12 | 0 |
| 2012-10-11 | 0 |
| 2012-10-10 | 7 |
+------------+-------------+
Would be returned.
How would this be approached?
When I did this a couple of years ago I created an empty array with the date as key and the default value 0. Then I simply looped through the result att changed the value for those dates I had.
for each($result as $row){
$date_stats_array[$row['date']] = $row['value'];
}
In situations like this I create a temporary table which I fill with all the dates you want. After that, you can use that table to join your original query against.
To fill the table you can use this procedure:
DROP PROCEDURE IF EXISTS filldates;
DELIMITER |
CREATE PROCEDURE filldates(dateStart DATE, dateEnd DATE)
BEGIN
WHILE dateStart <= dateEnd DO
INSERT INTO tablename (_date) VALUES (dateStart);
SET dateStart = date_add(dateStart, INTERVAL 1 DAY);
END WHILE;
END;
|
DELIMITER ;
CALL filldates('2011-01-01','2011-12-31');
Courtesy of https://stackoverflow.com/a/10132142/375087

Categories