check room availability with date range - mysql

Hello i have 2 tables rooms and bookings but my table sturcture little bit different,
in bookings table there are roomid,date,status for example:
101,2012-12-10,0
101,2012-12-11,0
101,2012-12-12,1
101,2012-12-13,0
102,2012-12-10,0
102,2012-12-11,0
102,2012-12-12,0
and i would like to find available rooms between 2012-12-10 and 2012-12-13
according this request only room 102 should be return.
i've tried
SELECT id
FROM status
WHERE status='0'
AND date between '2012-12-10' AND '2012-12-13'
GROUP BY id
it doesn't work because even find only one available row it returns true for 101
so 101 is available for 2012-12-11 then showing like available but not okay for our data range.

This will select all rooms that have no row with status=1 in the interval you select. Notice that I am not using between: if status=1 on 13th of December, the room is still available in the interval, that's why I'm using >= and <:
SELECT roomid
FROM status
WHERE `date` >= '2012-12-10'
AND `date` < '2012-12-13'
GROUP BY roomid
HAVING sum(status.status=1)=0
If there could also be some missing days in your table, and if that means that the room is not booked but also not available, you could also use this query:
SELECT roomid
FROM status
WHERE `date` >= '2012-12-10'
AND `date` < '2012-12-13'
AND status=0
GROUP BY roomid
HAVING count(*)=DATEDIFF('2012-12-13', '2012-12-10')
that checks that the number of days in the interval is equal to the number of rows with status=0.

If the date has a time associated with it you need to do something like this:
SELECT id
FROM status
WHERE status='0'
AND date between '2012-12-10 00:00:00' AND '2012-12-13 23:59:59'
GROUP BY id
You can also use Date(date) instead of including times, but this might be less efficient.

You should be able to use the following:
SELECT roomid
FROM status s1
WHERE status='0'
AND date between '2012-12-10' AND '2012-12-13'
and not exists (select roomid
from status s2
where status='1'
AND date between '2012-12-10' AND '2012-12-13'
and s1.roomid = s2.roomid)
GROUP BY roomid
See SQL Fiddle with demo

Try this:
SELECT rd.*
FROM room_details rd
INNER JOIN (SELECT DISTINCT roomid FROM bookings
WHERE roomid NOT IN (SELECT roomid FROM bookings
WHERE STATUS =0 AND DATE BETWEEN '2012-12-10' AND '2012-12-13')
) AS a ON rd.roomid = a.roomid

The SQL BETWEEN condition will return the records where expression is within the range of value1 and value2 (inclusive). So row 101,2012-12-10,0 should be returned for above mentioned query.

Try this:
SELECT roomid
FROM status
WHERE 'date_from' <= "2012-12-10" AND 'date_to' > "2012-12-10" AND 'status'= 0;

Related

MySQL SELECT SUM CASE with GROUP BY or DISTINCT

I'm trying to count unique user ids in a log table by month. So far I came up with the following query:
SELECT
COUNT(CASE WHEN log_date LIKE '2020-01%' THEN 1 END) AS januari
FROM user_log;
This query returns the total of all rows of the user_log in januari. However I would like to know how many unique users have logged in in Januari. So I need something like:
SELECT
COUNT(**DISTINCT user_id** CASE WHEN log_date LIKE '2020-01%' THEN 1 END) AS januari
FROM user_log;
I also tried GROUP BY, but so far no luck. Does anyone have a suggestion?
Consider:
SELECT COUNT(DISTINCT CASE WHEN log_date >= '2020-01-01' AND log_date < '2020-02-01' THEN userid END) AS januari
FROM user_log;
I changed the filtering logic to use half-open intervals rather than string matching: it is more efficient.
Note that, if you just that result for January, it is sufficient to use a WHERE clause:
SELECT COUNT(DISTINCT userid) januari
FROM user_log
WHERE log_date >= '2020-01-01' AND log_date < '2020-02-01'

SQL: Count/ sum columns within a specific date range

I have a table that roughly looks like this. There are thousands of rows.
booking_date checkin_date ...some other columns .... booking_value
22-mar-2016 29-mar-2016 ........................... $150
01-apr-2016 17-may-2016 ........................... $500
09-apr-2016 09-apr-2016 ........................... $222
17-apr-2016 23-apr-2016 ........................... $75
19-apr-2016 31-july-2016 ........................... $690
03-May-2016 07-May-2016 ............................. $301
.
.
.
.
I am trying to calculate number of bookings per day and the value of bookings per day in April 2016. The second part is to calculate for how many bookings the booking_date and checking_date were the same.
I am very new to SQL. I can formulate the logic in paper, but can't seem to figure out how to proceed with the code.
I recommend the following query:
SELECT CAST(booking_date AS DATE), COUNT(*) as Number_of_Booking,
SUM(CAST(booking_date AS DATE) = CAST(checkin_date AS DATE)) as count_with_same_date,
SUM(booking_value) as booking_value
FROM t
WHERE booking_date >= '2016-04-01' AND
booking_date < '2016-05-01'
GROUP BY CAST(booking_date AS DATE);
In particular, note the filtering on the dates. The direct comparisons allow MySQL to use an index.
The calculation of the number on the same date uses a nice feature of MySQL where boolean values are treated as numbers in a numeric context.
You can try this below code-
SELECT CAST(booking_date AS DATE),
COUNT(*) Number_of_Booking,
COUNT(
CASE
WHEN CAST(booking_date AS DATE)
= CAST(checkin_date AS DATE) THEN 1
ELSE NULL
END
) count_with_same_date,
SUM(booking_value) booking_value -- Booking value has to be Number field
FROM your_table
WHERE YEAR(booking_date ) = 2016
AND MONTH(booking_date ) = 4
GROUP BY CAST(booking_date AS DATE)
For the first question you can try
Select booking_date
,count(*) as Number_of_bookings
,Sum(booking_value) as value
From table_name
Where booking_date between '01-apr-2016' and '30-apr-2016'
group by booking_date:
Or you can use month() and year() function in filter.
For the second question try,
Select booking_date
,checkin_date
,count(*)
from table_name
where booking_date=checkin_date
group by booking_date, checkin_date

Getting total average between dates

I have a table named sales with the following format.
sale_id user_id sale_date sale_cost
j847bv-6ggd bd48ta36-cn5x 2017-01-10 15:43:12 30
vf87x2-15gr bd48ta36-cn5x 2017-01-05 13:41:16 60
3gfd7f-2cdd 8g4f5ccf-1fet 2017-01-15 14:10:12 100
4bgfd5-12vn 8g4f5ccf-1fet 2017-01-20 19:47:14 20
b58e32-bf87 8g4f5ccf-1fet 2017-01-20 17:35:13 15
bg87db-127g gr4gg1f4-3gbb 2017-01-20 12:26:15 80
How could I get the average amount that a user (user_d) spends within the first X amount of days since their first purchase? I don't want an average for every user, but a total average for all.
I know that I can get the average using select avg(sale_cost) but I'm unsure how to find out the average for a date period.
You can find average of total for each user within 10 days date range from intial sales date like this:
select avg(sale_cost)
from (
select sum(t.sale_cost) sale_cost
from your_table t
join (
select user_id, min(sale_date) start_date, date_add(min(sale_date), interval 10 day) end_date
from your_table
group by user_id
) t2 on t.user_id = t2.user_id
and t.sale_date between t2.start_date and t2.end_date
group by t.user_id
) t;
It finds the first sale_date and date 10 days after this for each user. Then joins it with the table to get total for each user within that range and then finally average of the above calculated totals.
Demo
If you want to find the average between overall first sale_date (not individual) and 10 days from it, use:
select avg(sale_cost)
from (
select sum(t.sale_cost) sale_cost
from your_table t
join (
select min(sale_date) start_date, date_add(min(sale_date), interval 10 day) end_date
from your_table
) t2 on t.sale_date between t2.start_date and t2.end_date
group by t.user_id
) t;
Demo
The between operator comes in handy whenever it comes to checking ranges
SELECT column_name(s)
FROM table_name
WHERE column_name BETWEEN value1 AND value2;
In this case value1 and value2 will be replaced by your dates using:
'2011-01-01 00:00:00' AND '2011-01-31 23:59:59'
or
sale_date AND DATE_ADD(OrderDate,INTERVAL 10 DAY)
The first way is faster and also the between values are inclusive.

Return active users in the last 30 days for each day

I have a table, activity that looks like the following:
date | user_id |
Thousands of users and multiple dates and activity for all of them. I want to pull a query that will, for every day in the result, give me the total active users in the last 30 days. The query I have now looks like the following:
select date, count(distinct user_id) from activity where date > date_sub(date, interval 30 day) group by date
This gives me total unique users on only that day; I can't get it to give me the last 30 for each date. Help is appreciated.
To do this you need a list of the dates and join that against the activities.
As such this should do it. A sub query to get the list of dates and then a count of user_id (or you could use COUNT(*) as I presume user_id cannot be null):-
SELECT date, COUNT(user_id)
FROM
(
SELECT DISTINCT date, DATE_ADD(b.date, INTERVAL -30 DAY) AS date_minus_30
FROM activity
) date_ranges
INNER JOIN activity
ON activity.date BETWEEN date_ranges.date_minus_30 AND date_ranges.date
GROUP BY date
However if there can be multiple records for a user_id on any particular date but you only want the count of unique user_ids on a date you need to count DISTINCT user_id (although note that if a user id occurs on 2 different dates within the 30 day date range they will only be counted once):-
SELECT activity.date, COUNT(DISTINCT user_id)
FROM
(
SELECT DISTINCT date, DATE_ADD(b.date, INTERVAL -30 DAY) AS date_minus_30
FROM activity
) date_ranges
INNER JOIN activity
ON activity.date BETWEEN date_ranges.date_minus_30 AND date_ranges.date
GROUP BY date
A bit cruder would be to just join the activity table against itself based on the date range and use COUNT(DISTINCT ...) to just eliminate the duplicates:-
SELECT a.date, COUNT(DISTINCT a.user_id)
FROM activity a
INNER JOIN activity b
ON a.date BETWEEN DATE_ADD(b.date, INTERVAL -30 DAY) AND b.date
GROUP by a.date

match timestamp with date in MYSQL using PHP

I have a table
id user Visitor timestamp
13 username abc 2014-01-16 15:01:44
I have to 'Count' total visitors for a 'User' for last seven days group by date(not timestamp)
SELECT count(*) from tableA WHERE user=username GROUPBY __How to do it__ LIMIT for last seven day from today.
If any day no visitor came so, no row would be there so it should show 0.
What would be correct QUERY?
There is no need to GROUP BY resultset, you need to count visits for a week (with unspecified user). Try this:
SELECT
COUNT(*)
FROM
`table`
WHERE
`timestamp` >= (NOW() - INTERVAL 7 DAY);
If you need to track visits for a specified user, then try this:
SELECT
DATE(`timestamp`) as `date`,
COUNT(*) as `count`
FROM
`table`
WHERE
(`timestamp` >= (NOW() - INTERVAL 7 DAY))
AND
(`user` = 'username')
GROUP BY
`date`;
MySQL DATE() function reference.
Try this:
SELECT DATE(a.timestamp), COUNT(*)
FROM tableA a
WHERE a.user='username' AND DATEDIFF(NOW(), DATE(a.timestamp)) <= 7
GROUP BY DATE(a.timestamp);
i think it's work :)
SELECT Count(*)
from table A
WHERE user = username AND DATEDIFF(NOW(),timestamp)<=7