PHP/MySQL - Calculate Total for each Reservation - php

I've got a Reservation application, and I'd like to calculate the total number of meals needed by reservations date span.
My database has fields:
$name - Person reserving
$chkin - Check in date (DATE yyyy-mm-dd)
$chkout - Check out date (DATE yyyy-mm-dd)
$guests - Number of people in group
$meal - Eating meals (Yes/No)
So for each reservation I have:
// Days of Stay
$days = (strtotime($chkout) - strtotime($chkin)) / (60 * 60 * 24);
What I'm not sure of is how to do the calculation for each reservation in the database.
My calculation for each reservation would be something like:
$days * $guests
I would appreciate advice on this query... I'm trying to give a snapshot of how many meals will be need to be prepared for a given month, weeekend, etc.
Thank you!

Something like this:-
SELECT SUM(guests * DATEDIFF(IF(chkin < $start_range, $start_range, chkin), IF(chkout > $end_range, $end_range, chkout)))
FROM sometable
WHERE chkin < $end_range
AND chkout > $start_range
AND meal = 'Yes'
Uses DATEDIFF() to get the number of days between the check in date (or if later the start of the date range you are interested in) and the check out date (or if earlier the end of the date range you are interested in) where meal is 'yes' and multiplies that by the number of guests, then uses SUM() to add them up for all bookings.

You can use the MYSQL date diff to achieve a count of the days, then this can be multiplied by the number of guests. Finally you will need to select a date range for this search. Below are the basics or the MYSQL needed in order to get these values. This should put you on the right track to achieving what you want.
SELECT DATEDIFF(a.chkout,a.chkin) * a.guests as meals
FROM table as a
WHERE a.chkin > '0000-00-00' AND a.chkout < '0000-00-00
I have tested this with a table of mine and it appears to be working correctly, however, without much data I can only test lightly. If you have any issues, leave a comment and I will try to help further.
http://www.w3schools.com/sql/func_datediff.asp

I'll give you a snippet as a starting point.
Let's say you want the top 10 guests with the longest stay.
SELECT DATEDIFF(chkout, chkin) AS daysstaying FROM reservations ORDER BY daysstaying DESC LIMIT 10
You can do calculations in queries and use the AS operator to create an alias for the result. I'm leaving it to you to work out the specific query you need to obtain the results you need.
I would also suggest that you investigate using views if this query needs to be used often.
http://dev.mysql.com/doc/refman/5.5/en/views.html

I was able to use Kickstart's and Erik's reply to come up with a solution! Thanks!!
// Get Current Month
$current_month = date('F');
// Current timestamp is assumed, so these find first and last day of THIS month
$start_range = date('Y-m-01'); // hard-coded '01' for first day
$end_range = date('Y-m-t');
$sql = "SELECT SUM(DATEDIFF(a.chkout,a.chkin) * a.guests) AS meals
FROM reservations AS a
WHERE a.chkin > '$start_range' AND a.chkout < '$end_range'
AND meal = 'Yes' AND confirm = 'Yes'";
No I will work towards forecasting for upcoming months as well!

Related

How to check the time is overlap with the exist record in MYSQL?

For a booking system,
the booking record is store like this:
start_time (timeStamp)
duration (int)
It is in hour basis so the duration means how many hour is the booking. So , when I add a booking record, I would like to check whether the time interval is exist already (notice that overlap part of the pervious booking time also not allow).
I would like to write a SQL to select the data that is overlap, so if count row is 0 , then that means it is not overlap and allow to insert to table
Attempted something like
$start = $_POST['start'];
$duration = $_POST['duration'];
SELECT COUNT(1) FROM booking WHERE $start >= start_time AND end_time_from_post <= end_time_from_exist_record
so the only problem seems to be to get the endtime, thanks for helping.
First, you don't need to do an aggregation. You can just check the returned result set for any row (in this case, it makes little difference, because there is presumably 0 or 1 rows, but in other similar situations aggregation is unnecessary overhead).
Two periods overlap if one begins before the second ends and the first ends after the second starts:
select 1
from booking
where $start <= date_add(start_time, interval duration hour) and
date_add($start, interval $duration hours) >= start_time;
Note: depending on your definition of "overlap", these might be strict inequalities.

Returning a report for each date in a PHP array

What I am trying to do here is render a report for each date in the current month from a MYSQL table.
I have a table with rows in, which a lot have the same date. As you can see here
What I would like to do is for every date in the current month is see how many rows have been found in the MYSQL table for that date and then return it into an array. The final product will be a multidimensional array for every date in the current month. Something like this
array("dates"=>
array(
"1 feb"=>2, //the number of rows for that date found in the MYSQL table
"2 feb"=>8,
"3 feb"=>0
)
)
But the issue is I wouldn't have a clue where to start with the coding, like what PHP functions would I use? So I was hoping someone could push me in the right direction :)
Probably not working code but should point you in the right direction:
SELECT
SUM(money) AS sum,
`date`
FROM
money_table
WHERE
MONTH(`date`) = 2
GROUP BY
DAY(`date`)
Reference
GROUP BY
MONTH
DAY
You said you didn't have a table with all the dates. If you did, this would be trivial. Let's say you had such a table called calendar.
select calendardate
, ifnull(sum(money), 0) sum_of_money
from calendar left join money on calendardate = money.date
where calendardate >= {d '2013-02-01'}
and calendardate < {d '2013-03-01'}
group by calendardate
Other things that could be stored in the calendar table are fiscal information and holidays. It might be worth your while to create and maintain one.

Booking query does not consider arrival and departure day

I have been searching for an answer to this dilemma but found nothing. I was hoping you could help to find out what I am doing wrong.
I have a mysql query that selects only apartmens available as follow:
SELECT *
FROM apartments
WHERE apartment_ID NOT IN (SELECT apartment_ID
FROM bookings
WHERE startDate <= '$endingdate'
AND endDate >= '$startingdate')
The problem is that this query is not considering that i.e. departure day is an half day and it is available.
To explain better:
if table "booking" has a booking ending on 16-01-2011 and the search is from the 16-01-2011. The apartment should be available because that is an "half" day (the day of departure). The query seems to not consider this and does not show the apartment.
Please could you help?
Francesco
I'm not that familiar with MySQL data types , but are you sure that startDate and endDate are not stored with a time part as well. If that's the case then "16-01-2011 16:25" would not be less than or equal to "16-01-2011".
Take out the = signs from your sub query, or at least the last one if a place vacated on a date is always available on that date. That should check for apartments being vacated on the requested date. Also make sure that your data is escaped.
If availabilty depends on time then you will need to change your date fields to datetimes.

Selecting the next date in MySQL

I have a list of dates in a table in a MySQL database (the dates when a charity bookstall is to be held), which I want to display on a page. On one page I'm displaying the date of the next stall, and on another the dates of the stall in the next month. (Currently I'm using an unordered HTML list and selecting the dates with PHP, but it's a bit messy, and I also want to tie in the dates with the fundraising totals that are stored in the database).
I want to put the dates in a database though so that I can tie in the dates with the fundraising totals for each week. I'm thinking that once I can identify the date with the nearest up-coming date that I can use 'LIMIT 1' to select the next week's date for display, and 'LIMIT 4' say for where I need to display the dates for the next month, but what I can't figure out is how to identify the record with the nearest up-coming date - identifying the current date and then selecting the nearest date...I have a feeling there's probably one of the MySQL date functions that can be persuaded to help out in this, but can't figure out exactly how.
Any ideas on how I can do this?
If I understand correctly, you can just pick up next four dates that are after today.
In MySQL you could use the CURDATE() function for the 'today' bit, then apply an order and limit to your select statement. For example,
SELECT stall_date
FROM stall_dates
WHERE stall_date >= CURDATE() -- >= assumes you want today's to show too
ORDER BY
stall_date
LIMIT 4
Use ORDER BY stall_date DESC to reverse the ordering if needed.
If your column is a DATETIME field, you can identify the next by using SELECT...WHERE event_date > "2009-11-06" and ORDER BY event_date.
SELECT * FROM so_events
WHERE event_date > "2009-11-06 15:36:00"
ORDER BY event_date ASC
LIMIT 4
MySQL will internally do the work for you and select rows where whose timestamp is greater than the one you specify in the WHERE clause.

Trying to filter a mysql table by date using a single query

I'm trying to request any records from a table that appear on or after today's date, using a single query.
All the dates for each record are stored in separate columns e.g.. - one for month, one for year, and one for day.
obviously i've been getting all records that occur after the year in today's date
$sql = "SELECT * FROM table WHERE year>=".$year_today."
ORDER BY year, month, day";
Then i've been trying to filter that down a bit, by using:
$sql = "SELECT * FROM table
WHERE year>=".$year_today." && month>=".$month_today."
&& day>=".$day_today."
ORDER BY year, month, day";
And in order to test it, i created a record in the database with yesterdays date, yet, this record still appears in the list of returned records. What am i doing wrong? :(
This can be achieved using time functions in a nice way, while it's better when using a DATE column.
SELECT * FROM TABLE WHERE TIMESTAMP(CONCAT(year,"-",month,"-",day)) >= CURDATE()
ok, that's evil as it doesn't use an index ... proper thing would be a DATE column, but doing all this by hand is annoying asyou also have to consider the case where year is bigger but months is smaller and stuff ....
I don't know if you can use "&&" instead of "AND" in your context - maybe try changing your SQL to use
" AND month>=".$month_today." AND day>=".$day_today."
EDIT :
as an extension to Nick's answer, to make the sql behave correctly you could code :
$sql = "SELECT * FROM table WHERE (
(year>".$year_today.")
OR (year=".$year_today." && month>".$month_today." )
OR (year=".$year_today." && month=".$month_today."&& day>=".$day_today.")
)
ORDER BY year, month, day";
...but this starts to get a whole lot messier than converting to dates and using date comparison
EDIT2:
but then again, if these columns are indexed, the indexes might be used. It's still a lot more effort to code SQL this way if performance using conversion to dates is totally acceptable.
To compare dates with dates:
SELECT * FROM table WHERE
STR_TO_DATE(
CONCAT(year
, '-'
, right(concat('00', month), 2)
, '-'
, right(concat('00', day), 2))
, '%Y-%m-%d')
>= STR_TO_DATE('2009-12-11', '%Y-%m-%d')
to check if a date is after another date this query will fail:
$sql = "SELECT * FROM table WHERE year>=".$year_today." && month>=".$month_today." && day>=".$day_today." ORDER BY year, month, day";
day 12 march of februari is smaller then day 15 in februari, but is still after it, because it's in a different month....

Categories