I'm trying to make a booking system and I came across a mistake.
I have a starting date and a ending date, if I enter a date start en end that falls between a booking already made the system is saying that is not possible, however if I enter before and after a already occupied period the system accepts the booking
this how I check now
`$db_check_result1 = mysql_query("SELECT * FROM ms_bookings WHERE ms_bookings_calid = '$propertyId' AND '$convertedstartdate' BETWEEN ms_bookings_startdate AND ms_bookings_enddate") or die(mysql_error());
if the result is greater than 0 then booking date is not possible and I do the samen with the departure date
$db_check_result2 = mysql_query("SELECT * FROM ms_bookings WHERE ms_bookings_calid = '$propertyId' AND '$convertedenddate' BETWEEN ms_bookings_startdate AND ms_bookings_enddate") or die(mysql_error());
again if the result is greater than 0 then booking is not possible
it works fine if new request falls within a already entered booking but when arrivaldate and departure date is before and after existing date the systems accepts
how can I solve this?
To get it out of the way:
Don't use mysql_* functions in any new code. The mysql extension has been removed from current PHP versions (starting with PHP 7.0). Use mysqli (note the "i") or pdo_mysql instead.
Don't put any user data directly into your queries. This will lead to security problems in the future (SQL injection). Use placeholders instead.
That said, the third check you want is
SELECT * FROM ms_bookings
WHERE ms_bookings_calid = :propertyId
AND (ms_bookings_startdate BETWEEN :convertedstartdate AND :convertedenddate
OR ms_bookings_enddate BETWEEN :convertedstartdate AND :convertedenddate)
However, you can combine all checks into a single simpler query:
SELECT * FROM ms_bookings
WHERE ms_bookings_calid = :propertyId
AND :convertedstartdate <= ms_bookings_enddate
AND :convertedenddate >= ms_bookings_startdate
In order to not overlap, the new booking has to either start after the existing booking ends (:convertedstartdate <= ms_bookings_enddate will be false then), or it has to end before the existing booking starts (:convertedenddate >= ms_booking_startdate is false).
Related
Trying to pull client information from SQL server using PHP and count how many clients signed up last month based on the date they signed up. I want to use DATEPART and DATEADD to specify the parameters I want for grabbing last months information, but the server doesn't seem to recognize these parameters. Currently using MySQL 5.6.44.
I know statements like
SELECT CLIENT_EMAIL
FROM CLIENT_TABLE
AND DATE_CLIENT_ADDED > (CURRENT_DATE() - INTERVAL 30 DAY)
works, but this is very limiting
$con = mysqli_connect($Host, $User, $Password, $DB);
$getLastMonthEnrollments = "SELECT CLIENT_EMAIL FROM CLIENT_TABLE AND DATEPART(m, DATE_CLIENT_ADDED) = DATEPART(m, DATEADD(m, -1, getdate()))";
$tempQuery = mysqli_query($con, $getLastMonthEnrollments);
$LastMonthEnrollments = mysqli_num_rows($tempQuery);
I expect to get a number from counting the rows, but my result is null. When I attempt to run this within the server itself, I get
FUNCTION my_DB.DATEPART does not exist
Am I doing this wrong? I've read many documentations and questions on here and this seems to be the correct usage.
You are using SQL Server syntax from your Laravel code, yet the underlying database is MySQL. Here is your query, rewritten and also corrected:
SELECT CLIENT_EMAIL
FROM CLIENT_TABLE
WHERE MONTH(DATE_CLIENT_ADDED) = MONTH(CURDATE() - INTERVAL 1 MONTH);
I have been trying to pull records based on a specified date. In the DB I have a column where I store unix timestamps. The user has the option to select records based on a date. The user inputs: 08/08/2016 (for example)
How would I write my SQL statement to handle this?
$query .= "`".$o."` = '".date("Y-m-d",strtotime($v))."' AND ";
Here we see the line where part of the SQL statement is built, because more than one column could be targeted by the user during their search request.
Somehow I need to be able to turn $o (which is a column storing unix timestamps) into the Y-m-d format for comparison, as shown above and make this work in an SQL statement.
Any help would be appreciated.
EDIT
Here is what worked for me:
$query .= "".$o.">= '".strtotime($v)."' AND".$o."< '".(strtotime($v)+(24*60*60))."' AND ";
You can do something like:
"WHERE DATE(`$o`) = '".date("Y-m-d",strtotime($v))."'"
However this won't use indexes, so if you have a large table it will be slower. If you want to be able to use indexes you can do:
"WHERE `$o` >= ".date("Y-m-d",strtotime($v))."
AND `$o` < ".date("Y-m-d",strtotime($v))." + INTERVAL 1 DAY"
You can also try this approach and use UNIX_TIMESTAMP on MySQL.
$v = '2016-08-04';
$query .= "'".$o."' = UNIX_TIMESTAMP('$v') AND ";
So I'm trying to block voting for 24hours after a user has already voted, and I've been stuck for a while now. I tried working off this earlier post but I haven't had any luck. I was able to echo the ip address but not the vote_time
I have a database with a table named voterlist that has two columns: submission_ip and vote_time. (the time is formatted like this date("Y-m-d H:i:s",time()) )
My php looks like this:
<?php
$ip = mysql_real_escape_string($_SERVER['REMOTE_ADDR']);
$query = "SELECT vote_time FROM voterlist WHERE submission_ip ='$ip'";
$result = mysql_query($query);
if(mysql_num_rows($result) < date('Y-m-d H:i:s',strtotime('-24 hour'))) {
echo 'you can vote again in 24 hours';
}else {
echo 'vote now';
}
?>
Any help with this query would be greatly appreciated.
In your line
if(mysql_num_rows($result) < date('Y-m-d H:i:s',strtotime('-24 hour'))) {
What are you trying to do here exactly?
The first term, mysql_num_rows($result) is the amount of rows the query returned. The second term, date('Y-m-d H:i:s',strtotime('-24 hour')) is some date string, like 2015-01-25 22:47:00. You're comparing them, why?
Instead, check for the date in the query:
SELECT vote_time FROM voterlist WHERE submission_ip ='$ip' AND `vote_time` > timestampadd(day, -1, now())
Then, if mysql_num_rows($result) gives you 1 or more, that means there is a record, so there has been a vote in the last 24 hours. If the number of rows is 0, there has not been a vote in the last 24 hours.
Besides that, blocking by IP is a bad idea. Do you want to block a whole company after one employee has voted? You could use authentication with some OpenID provider to ensure people only vote once, however, privacy may be an issue. If you have a list of the people who are allowed to vote (and it's not 'everyone') you could look into systems as RIES, which was used in some elections in the Netherlands a few years ago. (In 2008 the software was released and shown to have extensive security problems.)
Also note that the mysql_* functions have been deprecated (docs) in favour of PDO_MySQL and mysqli_*.
I have this table and the query I give returns wrong results, I am not sure where the problem is
the date comparisons
or
structure of the query
The query if not clear in the image is :
select * from transact where item_code='msft234' or item_code='hp550x' and transact_date>=STR_TO_DATE('06-07-2013','%d-%m-%Y') and transact_date<=STR_TO_DATE('12-07-2013','%d-%m-%Y')
Your query employs a wrong syntax:
WHERE item_code='msft234' OR item_code='hp550x'
AND transact_date>=STR_TO_DATE('06-07-2013','%d-%m-%Y')
AND transact_date<=STR_TO_DATE('12-07-2013','%d-%m-%Y')
since AND priority is higher, it means that it will be satisfied if either you get hp550x in that date interval, or you get msft234 regardless of the date.
You have to put the OR'ed item codes in parentheses: (item_code='..' OR item_code='..' OR ..), or use IN: e.g.
SELECT * FROM transact
WHERE item_code IN ('msft234', 'hp550x')
AND transact_date BETWEEN
STR_TO_DATE('06-07-2013','%d-%m-%Y')
AND
STR_TO_DATE('12-07-2013','%d-%m-%Y')
Also, depending on the type you select for the date fields, consider that for a date to be "less or equal than 12-07-2013", it has to be less or equal than 12-07-2013 at 00:00, i.e., almost the latest date that will match is 11-07-2013 at 23:59:59.
So "less or equal than 12-07" will actually never select any row from 12-07-2013 unless it happens to have been inserted exactly at midnight.
If you insert rows by only specifying the date, then it will very probably work - the rows will be input at midnight and matched at midnight. But if (some) rows are entered with the full datetime, e.g. because they're type datetime and updated with NOW(), then they will not match.
put the item conditions between ()
(ítem_code = 'msft234' OR ítem_code = 'hp550x') AND transact_date>=STR_TO_DATE('06-07-2013','%d-%m-%Y') and transact_date<=STR_TO_DATE('12-07-2013','%d-%m-%Y')
(ítem_code = 'msft234' OR ítem_code = 'hp550x') AND transact_date BETWEEN STR_TO_DATE('06-07-2013','%d-%m-%Y') and STR_TO_DATE('12-07-2013','%d-%m-%Y')
For security I will put with 2 ()
(ítem_code = 'msft234' OR ítem_code = 'hp550x') AND (transact_date BETWEEN STR_TO_DATE('06-07-2013','%d-%m-%Y') and STR_TO_DATE('12-07-2013','%d-%m-%Y'))
I am unable to get the following code to work:
// dd/mm/yyyy for dates in SQL queries
$todayforw = date('d/m/Y');
$aweekago = date('d/m/Y', time() - 604800);
$week_e_check = mysql_query("SELECT * FROM earningslog WHERE user_id = '".$info['id']."' WHERE day >='".$aweekago."' AND day <'".$todayforw."'");
while ($week_e_info = mysql_fetch_array($week_e_check)) {
$week_e = $week_e + $week_e_info['user_earnings_amnt'];
}
The query returns zero rows, however, it should be returning data that matches the criteria.
Check your date format:
Should be:
YYYY-mm-dd HH:mm:ss
E.G.
2012-01-01 00:00:00 (January 1, 2012 at midnight local time)
Other date formats MAY work, but the best way to go about it is to use the same format that MySQL uses when they display the date, that's the only way I know that works every time.
http://dev.mysql.com/doc/refman/5.5/en/date-and-time-functions.html
Also your syntax is incorrect, you have two wheres, you should use AND.
Take a closer look at your query:
SELECT * FROM earningslog WHERE user_id = '".$info['id']."' WHERE day >='".$aweekago."' AND day <'".$todayforw."'"
Your Where clause appears twice.
Two things to think about - when you are selecting data, try and stay away from select * - you may get unexpected results of the table is ever modified.
Second, try and create the query as a parameterized query, instead of injecting the parameters directly into the where clause. By directly injecting your criteria the way you have, you are opening yourself up to a SQL injection attack.
By turning it into a parameterized query, you get the side benefit of being able to debug the queries directly against the database, reducing the amount of effort needed to copy it from a query tool into your code.
Your issue appears to be with your query syntax. You are stating WHERE twice, whereas you should only state it once and then use the AND or OR operators for further criteria. I would also suggest that you either move your statement into a variable or use die() to assist with debugging.
$week_e_check = mysql_query("SELECT * FROM earningslog WHERE user_id = '".$info['id']."' AND day >='".$aweekago."' AND day <'".$todayforw."'") or die(mysql_error());
In addition, you should not be using the mysql extension as use of this extension is discouraged. Instead, use the MySQLi or PDO_MySQL extension. Using one of these alternative extensions will help serve as the first step in preventing SQL injection. I would also suggest that you avoid using * and specify the column names to be returned instead.
Using PDO:
<?php
/* Execute a prepared statement by passing an array of values */
$sth = $dbh->prepare('SELECT * FROM earningslog WHERE user_id = ? AND day >= ? AND day < ?');
$sth->execute(array($info['id'], $aweekago, $todayforw));
$results = $sth->fetchAll();
?>
Try change the format of your strings from from d/m/Y to Y-m-d.
MySQL might be expecting it year first. In which case it could be doing the wrong thing with d/m/Y.
Also don't use the WHERE clause twice. Instead, combine conditions using AND, eg:
WHERE user_id = '".$info['id']."'
AND day >='".$aweekago."'
AND day <'".$todayforw."'
By the way, you can also try saying WHERE day BETWEEN ".$aweekago." AND ".$todayforw.", which might be easier syntax to read (as long as you change $todayforw to be the day before).