Issue displaying correct week from MySQL database - php

I have a expenses script that displays the current week by week number based on week number in the database (w10) and can select other weeks by using ?selectWeek=w46
We have been using this script for a year now and does not show the information for this week (w10) because there are 2 entries in the database for w10 and it's getting confused which one to display.
Database Structure
ID - Base_Charge - Week - Year - Created_ At
1 - 20000 - w10 - 2021 - 2021-03-08
53 - 454333 - w10 - 2022 - 2022-03-07
Code:
<?php
include '../main.php';
check_loggedin($pdo);
// output message (errors, etc)
$msg = '';
$stmt = $pdo->prepare('SELECT * FROM expense_base_charge');
$stmt->execute();
$weekList = $stmt->fetchAll(PDO::FETCH_ASSOC);
if(isset($_GET['selectWeek'])){
$week = $_GET['selectWeek'];
}else{
$ddate = date('y-m-d');
$date = new DateTime($ddate);
$week = 'w'.$date->format("W");
}
$stmt = $pdo->prepare('SELECT * FROM expense_base_charge where week = ?');
$stmt->execute([$week]);
$base_charge = $stmt->fetch(PDO::FETCH_ASSOC);
$stmt = $pdo->prepare('SELECT * FROM expense where week = ?');
$stmt->execute([$base_charge['id']]);
$expense = $stmt->fetchAll(PDO::FETCH_ASSOC);
?>
Any idea how to make it view the correct week please?

When you want select only current year records you can improve your where statement in next way:
$week = 'w10';
$stmt = $pdo->prepare(
'SELECT * FROM expense_base_charge WHERE week = ? AND year = YEAR(NOW())'
);
$stmt->execute([$week]);
$base_charge = $stmt->fetch(PDO::FETCH_ASSOC);
PHP MySQL Feddle
Another way, you can calculate default week/year values in PHP
(in next example I also changed week column format to int)
//set current week/year values when they not provided by GET
$week = $_GET['selectWeek'] ?? date('W');
$year = $_GET['selectYear'] ?? date('Y');
//debug only print
printf('YEAR: %d, WEEK: %d ' . PHP_EOL, $year, $week);
//select data fom MySQL using week & year
$stmt = $pdo->prepare(
'SELECT * FROM expense_base_charge WHERE week = ? AND year = ?'
);
$stmt->execute([$week, $year]);
$base_charge = $stmt->fetch(PDO::FETCH_ASSOC);
Test online

The problem is that you are storing the value for week and year in a denormalized form. The week number should not be stored with prefix w. Ideally, you would store both of them in a single column. Then you could use YEARWEEK() function in SQL.
This is of course assuming that you are using ISO 8601 week numbering. If you are not following this scheme then fetching the correct value will be very difficult.
If you don't want to change the table schema now, you can still get the same value using PHP. Use 'o' for year number and 'W' for week number.
$week = $_GET['selectWeek'] ?? 'w'.(new DateTime())->format("W");
$year = $_GET['selectYear'] ?? (new DateTime())->format("o");
$stmt = $pdo->prepare('SELECT * FROM expense_base_charge where week = ? and year = ?');
$stmt->execute([$week, $year]);
$base_charge = $stmt->fetch(PDO::FETCH_ASSOC);

Related

Update Mysql row where date equal to todays date

I am trying to update a row in my table where the date in a column is equal to today's date.
I have today's date in a variable $currentDate and when I echo this out it is displayed on the screen in the following format
2020-05-08
Which looks same format as the Db table, but I still get the error invalid datetime format.
Below is the code I'm using. Any help please
$currentDate = date("Y-m-d");
$currentTemp = 33;
echo $currentDate;
$sql = "UPDATE weather_station SET currentTemp = $currentTemp WHERE date = $currentDate";
$stmt = $pdo->prepare($sql);
$stmt->execute();
$sql = "UPDATE weather_station SET currentTemp = :temp WHERE date = :currenDate";
$stmt = $pdo->prepare($sql);
$stmt->bindParam(":temp", $currentTemp);
$stmt->bindParam(":currenDate", $currentDate);
$stmt->execute();
This works now

updating a datetime sql value by exactly a year

im trying to get a datetime variable (example: 2019-02-10 03:13:33) to update exactly a year. i read that datetime is written as a string so i tried to subtract by itself and add +365.
the code works if i take out all "expirationdate" including the bind value. also for some reason, i have to keep my UPDATEs encased in single quotations because theres no changes in my database if they are inside double quotes.
$stmt = $db->prepare('UPDATE usr_customer_profile SET packageid = 3, expirationdate = .'$oneyear'. WHERE usrcustomerid = :usrcustomerid');
$stmt->bindValue(':expirationdate', $_SESSION['expirationdate'], PDO::PARAM_STR);
$stmt->bindValue(':usrcustomerid', $_SESSION['usrcustomerid'], PDO::PARAM_INT);
$oneyear = (':expirationdate' - ':expirationdate') + 365;
$stmt->execute();
You can do this in PHP or SQL. In PHP you can use strtotime or (preferably) the DateTime class to add one year to the value in $_SESSION['expirationdate']:
// using strtotime
$expirationdate = date('Y-m-d H:i:s', strtotime($_SESSION['expirationdate'] . ' + 1 year'));
// using DateTime
$expiration = new DateTime($_SESSION['expiration_date']);
$expiration->add(new DateInterval('P1Y'));
$expirationdate = $expiration->format('Y-m-d H:i:s');
// do the query
$stmt = $db->prepare('UPDATE usr_customer_profile
SET packageid = 3,
expirationdate = :expirationdate
WHERE usrcustomerid = :usrcustomerid');
$stmt->bindValue(':expirationdate', $expirationdate, PDO::PARAM_STR);
$stmt->bindValue(':usrcustomerid', $_SESSION['usrcustomerid'], PDO::PARAM_INT);
$oneyear = (':expirationdate' - ':expirationdate') + 365;
$stmt->execute();
In SQL use + INTERVAL 1 YEAR to add 1 year to the expiration date:
$stmt = $db->prepare('UPDATE usr_customer_profile
SET packageid = 3,
expirationdate = :expirationdate + INTERVAL 1 YEAR
WHERE usrcustomerid = :usrcustomerid');
$stmt->bindValue(':expirationdate', $_SESSION['expirationdate'], PDO::PARAM_STR);
$stmt->bindValue(':usrcustomerid', $_SESSION['usrcustomerid'], PDO::PARAM_INT);
$oneyear = (':expirationdate' - ':expirationdate') + 365;
$stmt->execute();

Between clause is returning 0 records

I have 3 records in the database matching the criteria but when I run query with between clause it is getting 0 records.
$current_date = date('m-d-Y', strtotime('monday this week'));
$upcoming_date = date('m-d-Y', strtotime('monday next week'));
$sql = mysqli_query($connection, "SELECT * FROM result WHERE test_date BETWEEN $current_date AND $upcoming_date AND login = '".$_SESSION['uid'] ."'");
$total_check = mysqli_num_rows($sql);
Here is my database
result_id`, `login`, `test_id`, `test_date`,
(1, '2', 6, '08-03-2016',
(2, '2', 5, '08-03-2016',
(3, '2', 3, '08-03-2016',
Please let me know where and what I am doing wrong as I am getting 0 results and $_SESSION['uid'] is 2
You should use ' for $current_date AND $upcoming_date
"SELECT * FROM result WHERE test_date BETWEEN '$current_date' AND '$upcoming_date' AND login = '".$_SESSION['uid'] ."'"
Use prepare statement like below to avoid SQL Injection
$stmt = $dbConnection->prepare('SELECT * FROM employees WHERE name = ?');
$stmt->bind_param('s', $name);
$stmt->execute();
$result = $stmt->get_result();
while ($row = $result->fetch_assoc()) {
// do something with $row
}
You are storing your dates incorrectly if you want to use them in range searches like BETWEEN. You must store them in DATE columns. Storing them in VARCHAR() columns is a bad idea.
You could use something like this, using STR_TO_DATE() to work around your misdesigned table.
$current_date = date('Y-m-d', strtotime('monday this week'));
$upcoming_date = date('Y-m-d', strtotime('monday next week'));
$sql = mysqli_query($connection, "SELECT * FROM result WHERE STR_TO_DATE(test_date,'%d-%m-%Y') BETWEEN '$current_date' AND '$upcoming_date' AND login = '".$_SESSION['uid'] ."'");
To ask MySQL to compare the strings 01-01-2016 and 12-31-2015, and determine that the latter comes before the former is unreasonable. String comparison is lexical. However, 2015-12-31 obviously comes before 2016-01-01.
This is a little tricky to get right, because the text string 08-08-2016 does come before 08-15-2016, by accident. But at the end of year, things collapse.

MYSQL - Selecting Dates of Current Work Week

I'm am writing a PHP program that will get all of the dates for the current work week (excluding Monday). My code is as follows:
//Get Year
$sql = "SELECT YEAR(CURDATE()) AS CurYear";
$result = mysqli_query($db, $sql);
$row = mysqli_fetch_array($result,MYSQLI_ASSOC);
$curyear = $row['CurYear'];
//Get Week
$sql = "SELECT WEEK(CURDATE()) AS CurWeek";
$result = mysqli_query($db, $sql);
$row = mysqli_fetch_array($result,MYSQLI_ASSOC);
$curweek = $row['CurWeek'];
//Get Date of Tuesday
$sql = "SELECT STR_TO_DATE('$curyear$curweek Tuesday', '%X%V %W') AS TueDate";
$result = mysqli_query($db, $sql);
$row = mysqli_fetch_array($result,MYSQLI_ASSOC);
$tuedate = $row['TueDate'];
It works and will return the date of this Tuesday, but is there a more efficient way of doing this, and moreover doing it for the following 3 days?
As explained here: How to find the day of week from a date using PHP?
you can use the date command:
$time = time(); // present time
$day = 3; //the day of the week we are looking for 0: sunday, 1 monday and so on
$dayofweek = date('w', $time); //current day week number
$result = date('Y-m-d', strtotime(($day - $dayofweek).' day', $time));
I'm not sure if you have a requirement of using MySQL, but I would do this in PHP directly. Below is a sample of how you could approach it. Once the variable $TuesTS is set, you can figure out the next day by adding (24*60*60) or 86400 to it, which is the number of seconds in a day.
<?php
$ts = time();
$todayNum = date('N');
if ( ($todayNum >= 2) && ($todayNum<=5)){
$offset = $todayNum - 2; // number of days after Tuesday;
$TuesTS = $ts-($offset*24*60*60);
echo "Tuesday : ".date('Y-m-d', $TuesTS);
}
?>

Prevent repetitive rows

I have this table :
I would like to delete same rows. For example first five rows are the same, my table should have only one row that includes this data : 40.792274 29.412994 2011-12-21 17:19:52.
So I used the following code :
$query = "SELECT * FROM table GROUP BY date";
$result = mysql_query($query);
while($row = mysql_fetch_array($result)){
$date = $row['date'];
$lat = $row['latitude'];
$lon = $row['longitude'];
$query = "SELECT * FROM table WHERE date='$date' AND latitude='$lat' AND longitude='$lon'";
$re = mysql_query($query);
$number = mysql_num_rows($re);
$number--;
$query = "DELETE * FROM table WHERE date='$date' AND latitude='$lat' AND longitude='$lon' LIMIT $number";
mysql_query($query);
}
But this code doesn't work.. What should I do ?
Edited :
I solved my question :
$query = "SELECT * FROM table GROUP BY date";
$result = mysql_query($query);
while($row = mysql_fetch_array($result)){
$date = $row['date'];
$lat = $row['latitude'];
$lon = $row['longitude'];
$query = "SELECT * FROM table WHERE date='$date' AND latitude=$lat AND longitude=$lon";
$re = mysql_query($query);
$number = mysql_num_rows($re);
$number--;
$query = "DELETE FROM table WHERE date='$date' AND latitude=$lat AND longitude=$lon LIMIT $number";
mysql_query($query);
}
Query lines were incorrect in my first question.
To remove the duplicate elements, you would use something like this:
$q = "SELECT date FROM table GROUP BY date"
$r = mysql_query($r);
$date = '';
while($row = mysql_fetch_array($r)){
$date = $row['date'];
$q = "SELECT date FROM mytable WHERE date='$date'";
$re = mysql_query($q);
$num = mysql_num_rows($re);
$num--;
$q = "DROP FROM mytable WHERE date='$date' LIMIT $num";
mysql_query($q);
}
Should do the trick. More specifically, when creating your $date value, you have to provide PHP with a time to use. date() defaults to using the current time, but you can provide it with a custom time as the second argument.
I suggest you take a look at the strtotime() manual at php.net as well (To translate times in your db to timestamps that can be used with date() ).
EDIT: The Answer above has been edited to remove all duplicate entries.
Try changing $dateOfNewData = date('Y-m-d H:i:s');
to
$dateOfNewData = date('Y-m-d 00:00:00'); //or change the first 00 to H if you need it to match by hour, second 00 to i if you need to match minutes and the same with seconds.
or $dateOfNewData = date('Y-m-d') which is pretty much the same and works with datetime field types
And you also need to modify your query to something like this unless you need an exact time:
"SELECT * FROM mytable WHERE date = '$dateOfNewData'" // you might also want the end date if you're working with the past in your database.
Well you can try like "Ignas" suggest but you cal also try this:
First just get the date (year, month, day) without hour, minutes and seconds. If you use full date format then you need to match exactly the same time. (to second the same) which is not really what you are looking for i guess. So you can use this:
$dateOfNewData = date('Y-m-d'); //just get year, month, day in right format (2011-12-20)
Then run a query. Here you have more options but i think the easier is something like that:
"SELECT * FROM mytable WHERE date_col LIKE '$dateOfNewData%' GROUP BY date_col"
This will group the same dates together and will display just once and will match all the rows where 'date_col starts with example: 2011-12-20% (thats why i use LIKE and $dateOfNewData%)
$dateOfNewData contains current date in this format:year-month-day (2011-12-20) and in Mysql query dont forget to use % at the end of the date. It's like * in windows for example.
'mytable' replace with your table name and 'date_col' with date column.
date() you have used will give current date time , so try to use mktime() to get extact date time you want.
you have to change your query little bit, I have modified query below,
$query = mysql_query("SELECT * FROM mytable WHERE date='$dateOfNewData'");
In mysql Date or datetime coulmn should be within ''.

Categories