I have above mysql table with available dates and prices. Second table includes room details. How can I join two tables to get available rooms between two dates and not get duplicate content.
This is hard to come up with a complete answer for you here, as you are only showing us the table which contains the bookings - we cannot know what range of rooms are available.
SQL which returns the room_id's for rooms which are booked for at least part of the selected period could be:
SELECT `room_id` , COUNT(*)
FROM `bookings`
WHERE `dt` BETWEEN "[start date]" AND "[end date]"
GROUP BY `room_id`;
If you had a table of rooms (rather than bookings), it would be possible for you to return a list of any rooms not booked during that period with:
SELECT `id`
FROM `rooms`
WHERE `id` NOT IN (
SELECT DISTINCT( `room_id` )
FROM `bookings`
WHERE `dt` BETWEEN "[start date]" AND "[end date]"
);
AMENDMENT
Based on the feedback by OP, the assumptions are now:
The table contains details of rooms which are available for a period starting on the date in column dt and ending the following day (ie hotel rooms)
The query should return any rooms which are available for the entirity of the period entered (so only rooms which are available from DAY A to DAY B will be returned.
As such, the amended code is:
SELECT room_id
FROM available_rooms
WHERE dt BETWEEN "[start date]" AND DATE_SUB("[end date]",INTERVAL 1 DAY)
GROUP BY room_id
HAVING COUNT(*)=ABS(DATEDIFF("[start date]","[end date]"));
SELECT available.* , rooms.* FROM available, rooms
WHERE available.room_id = rooms.room_id AND
available.dt BETWEEN '2005-01-01' AND '2005-12-31'
Assuming the table you showed us is called rooms_dates with two other tables rooms and room_details:
select room.id, room_details.xxxxxxx from rooms
inner join room_details on rooms.id = room_details.room_id
where rooms.id in
(
select distinct room_id from rooms_dates
where dt >= 'xxxx-xx-xx' and dt <= 'yyyy-yy-yy'
);
Related
in the above table i need sql query by which i can return dates between Leave_from and Leave_to from leave_log Table (eg, Leave_from 30/07/2018 Leave_to 02-08-2018) i need dates like
30/07/2018
01/08/2018
02/08/2018
by which i will try next query
2) is der any query or function which will check before insert into leave_log table whether the leaves applied by the employees for particular date (01-08-2018) does not cross quota of 10% per Team
Thanks in advance
First, you should have a calender table if yes, then you need to JOIN with your actual table to calender table. In other way you can use recursive CTE option :
with t as (
select id, leave_frm, leave_to
from table
union all
select id, dateadd(day, 1, leave_frm), leave_to
from t
where leave_frm < leave_to
)
select *
from t
option (maxrecursion 0);
I need to compute employees' monthly salaries based on meetings attended, deductions and bonuses given;
Employees have different pay per meeting based on their job position.
The solution is:
salary = (Pay_per_minute * meetings_attended) + bonuses - deductions ;
I have four tables:
Jobs: Id, title, pay_per_meeting
Employees: Id, Name, job_id
Bonuses: Id, amount, employee_id, date
Deductions: Id, amount, employee_id, date
Meetings: Id, employee_id, date
SELECT
COUNT(meetings.employee_id) as meetings_attended,
COUNT(deductions.amount) as debt,
COUNT(bonuses.amount) bonus,
(SELECT jobs.pay_per_attendance from jobs where jobs.id = (select job_id from employees where id=meetings.employee_id)) as pay,
((meetings_attended * pay) + bonus - debt) as salary
FROM meetings
JOIN deductions ON deductions.employee_id = meetings.employee_id
JOIN bonuses ON bonuses.employee_id = meetings.employee_id
WHERE meetings.employee_id = 1
GROUP BY MONTH(meetings.date), MONTH(deductions.date), MONTH(bonuses.date)
The above query returns many incorrect values whenever i remove the salary line but gives error of unknown column pay, meetings_attended, debt and bonus, am sure something is wrong with the grouping but i can't just see it.
You can't refer to column aliases in the same select list as they're defined, you need to refer to the underlying column. And a subquery can't access an aggregate calculated in the main query. You need to repeat the aggregate expression, or move everything into a subquery and do the calculation with it in an outer query.
Also, all your COUNT() expressions are going to return the same thing, since they're just counting rows (I assume none of the values can be NULL). You probably want COUNT(DISTINCT <column>) to get different counts, and you need to use a column that's unique, so they should be the primary key column, e.g. COUNT(DISTINCT deductions.id).
Another problem is that when you try to sum and count values when you have multiple joins, you end up with a result that's too high, because rows get duplicated in the cross product of all the tables. See Join tables with SUM issue in MYSQL. The solution is to calculate the sums from each table in subqueries.
SELECT m.month, m.meetings_attended, d.debt, b.bonus,
m.meetings_attended * j.pay_per_meeting + b.amount - d.amount AS salary
FROM (
SELECT MONTH(date) AS month, COUNT(*) AS meetings_attended
FROM meetings
WHERE employee_id = 1
GROUP BY month) AS m
JOIN (
SELECT MONTH(date) AS month, COUNT(*) AS bonus, SUM(amount) AS amount
FROM bonuses
WHERE employee_id = 1
GROUP BY month) AS b ON m.month = b.month
JOIN (
SELECT MONTH(date) AS month, COUNT(*) AS debt, SUM(amount) AS amount
FROM deductions
WHERE employee_id = 1
GROUP BY month) AS d ON m.month = d.month
CROSS JOIN employees AS e
JOIN jobs AS j ON j.id = e.job_id
WHERE e.employee_id = 1
I am trying to get unreserved hotel rooms according to a daterange which is given by user.
I have two tables
rooms with columns room_id, roomno
reservations with columns reserv_id, room_id, checkindate, checkoutdate
Im applying this query
$sql = "SELECT DISTINCT roomno
FROM rooms
LEFT JOIN reservation ON rooms.room_id = reservation.room_id
AND
(
(
(reservation.checkindate > '$newreservcheckin')
AND
(reservation.checkindate > '$newreservcheckout')
)
OR
(
(reservation.checkoutdate < '$newreservcheckin')
AND
(reservation.checkoutdate < '$newreservcheckout')
)
)";
$newreservcheckin and $newreservcheckout are date ranges provided by user
Let's say we have rooms with roomno as 100 and 101
now 100 is booked from 9-16-2016 to 9-18-2016
and 100 is also booked from 9-27-2016 to 9-29-2016
and room 101 is unreserved(meaning it has no record in reservation table)
Suppose if user gives dates 9-26-2016 to 9-30-2016 query will ignore the room no 100 entry which is from 9-27-2016 to 9-29-2016 but will show the room no 100 with dates from 9-16-2016 to 9-18-2016 and will show 101 room
How to mold the query so that it may not give the same room but the one with different dates?
You need to select the rooms which are either (A) Not booked or (B) Booked but outside the range you are querying for, below query should work:
select no from room r
where not exists (
select id from reservation where room_id = r.id)
union
select no from room r
where r.id not in (
select distinct room_id from reservation
where
checkindate between '2016-09-20' and '2016-09-22'
OR
checkoutdate between '2016-09-20' and '2016-09-22'
)
Here is the SQL Fiddle.
You can join every reservation that overlaps with new checking dates and select those rooms which have nothing to join. In my query I expect that new guests can checkin at the same date when previous would checkout. If not - change "<" to "<=" and ">" to ">=".
SELECT
r.roomno
FROM
rooms r
LEFT JOIN
reservations res ON res.room_id = r.room_id
AND res.checkindate < '$newreservcheckout'
AND res.checkoutdate > '$newreservcheckin'
WHERE res.reserv_id IS NULL
I have one table with a list of number of sales per month against product code and another with a list of months that can extend before or after the months that had a sale in. I need to results to show 0 sales if there were no sales in the month and for the cumulative to add this up. I have tried using case and if and getting it to put 0 if sales.sales was null but this did not work and I still just had blanks.
create table summary as (SELECT
q1.productid As productid,
q1.date AS Month_View,
q1.sales AS Monthly_Units_Sold,
(#runtot_sales := #runtot_sales + q1.sales) AS Cumulative_Sales
FROM
(SELECT
sales.productid,
dates.date,
if(sales.date is null,0,sales.sales) as sales
from
dates
left join sales on dates.date = sales.date
where
sales.productid = '$input1'
group by dates.date
ORDER BY date) AS q1);
";
Try COALESCE() function to return the first non-NULL value of a list Also see demo here
CREATE TABLE summary AS
(SELECT
q1.productid AS productid,
q1.date AS Month_View,
q1.sales AS Monthly_Units_Sold,
(
#runtot_sales := #runtot_sales + q1.sales
) AS Cumulative_Sales
FROM
(SELECT
sales.productid,
dates.date,
COALESCE(sales.sales, 0) AS sales
FROM
dates
LEFT JOIN sales
ON dates.date = sales.date
WHERE sales.productid = '$input1'
GROUP BY dates.date
ORDER BY DATE) AS q1) ;
MySQL COALESCE() function
You are misusing GROUP BY and therefore getting indeterminate results. See this: http://dev.mysql.com/doc/refman/5.5/en/group-by-extensions.html
If you're aggregating your items by product and date you probably want something like this.
SELECT sales.productid,
dates.date,
SUM(sales.sales) as sales
FROM dates
LEFT JOIN sales ON dates.date = sales.date
WHERE sales.productid = '$input1'
GROUP BY sales.productid, dates.date
ORDER BY /* i'm not sure what you're trying to do with the running total */
Note that SUM(sales.sales) handles the NULL values from your LEFT JOIN correctly. If the date doesn't join a sales row then sales.sales will be NULL.
If you're trying to do a month-by-month summary you need more logic than you have. See this writeup: http://www.plumislandmedia.net/mysql/sql-reporting-time-intervals/
I am programming a Hotel Reservation module. Now I have to connect an existing application to get the available rooms on a given range of dates. Please help me in this.
I am here posting the DB schema of the existing app (where the rooms and bookings info were stored).
rooms:
id
room_type
room_count
people
hotel_id
bookings:
id
from
to
name
email
people
dt
hotel_id
bookings_rooms
booking_id
room_id
quantity
I will give 3 inputs
Hotel ID
From Date
To Date
What I need is a list of room_id and max_qty_available
So, rooms aren't actually rooms, they are a type with a count. Does clear up a few things, although by rooms not being seperate entities it is very hard to prevent a change of rooms being eligable.
SELECT r.id, r.room_count - SUM(br.quantity ) AS max_qty_available
FROM rooms r
LEFT JOIN bookings b
ON b.hotel_id = r.hotel_id
AND b.from < <Date END>
AND b.to > <Date START>
LEFT JOIN booking_rooms br
ON br.room_id = r.id
AND br.booking_id = br.id
WHERE r.hotel_id = <Hotel ID>
I`m guessing what some of this parameters are, but here it goes:
Select id as room_id, room_Count as max_qty_available From Rooms Where
id Not in (Select room_id From Bookings_rooms Where booking_id
In (Select id From bookings Where from>=#FromDate And to <=#ToDate And hotel_id=#HotelID)
) And hotel_id = #HotelID
You can replace IN and NOT IN with Exists and Not exists if there is a performance issue. But not sure if Exists are supported in mysql.