Calculate the fullness of an apartment using SQL expression - mysql

I have a database which looks like this:
Reservations Table:
-------------------------------------------------
id | room_id | start | end |
1 | 1 | 2015-05-13 | 2015-05-16 |
2 | 1 | 2015-05-18 | 2015-05-20 |
3 | 1 | 2015-05-21 | 2015-05-24 |
-------------------------------------------------
Apartment Table:
---------------------------------------
id | room_id | name |
1 | 1 | test apartment |
---------------------------------------
Meaning that in the month 05 (May) there is 31 days in the database we have 3 events giving us 8 days of usage 31 - 8 = 23 / 31 = 0.741 * 100 = %74.1 is the percentage of the emptiness and %25.9 is the percentage of usage. how can i do all of that in SQL? (mySQL).

This is my proposal:
SELECT SUM(DAY(`end`)-DAY(`start`))/EXTRACT(DAY FROM LAST_DAY(`start`)) FROM `apt`;
LAST_DAY function gives as output the date of last day of the month.

Check this
http://sqlfiddle.com/#!9/7c53b/2/0
Not the most efficient query but will get the job done.
select
sum(a.days)*100/(SELECT DAY(LAST_DAY(min(start))) from test1)
as usePercent,
100-(sum(a.days)*100/(SELECT DAY(LAST_DAY(min(start))) from test1))
as emptyPercent
FROM
(select DATEDIFF(end,start) as days from test1) a
What I did is first get the date difference and count them. Then in a nested query use the day(last_day()) function to get the last day of month. Then calculated by using your logic.

Related

Mysql - Get season from current month

I have the following table of seasons:
| id | name | start_month | end_month |
------------------------------------------
| 101 | Summer | 12 | 2 |
| 102 | Winter | 6 | 8 |
| 103 | Spring | 9 | 11 |
| 104 | Fall | 3 | 5 |
I need to get the season by month. Say current month is 2 (February), I want Summer to be the output.
I can get other seasons to work by simply having the where condition start_month >= 4 and end_month <= 4. But this won't work with Summer since the season crosses into next year.
What do I have to do to handle the case of Summer?
One solution I thought was to use dates instead of month number like 1980-12-01 and use between function but it gets a bit complicated for the user end.
It'd be great if it could work with just month numbers.
You could do:
(month(d) between start_month and end_month) or
(start_month>end_month and (month(d)>=start_month or month(d)<=end_month))
See db-fiddle

SQL - select x entries within a timespan

I'm creating a database (in MySQL) with a table of measurements. For each measurement I want to store the DateTime it came in. For showing plots within an app for different intervals (measurements of the day/week/month/year) I want sample the data points I have, so I can return e. g. 30 data points for the whole year as well as for the day/hour. This is the same as done with stock price graphs:
stock price plot for 1 day
vs
stock price plot for 1 month
As you can see, the amount of data points is the same in both pictures.
So how can I select x entries within a timespan in MySQL via SQL?
My data looks like this:
+====+====================+=============+==========+
| id | datetime | temperature | humidity |
+====+====================+=============+==========+
| 1 | 1-15-2016 00:30:00 | 20 | 40 |
+----+--------------------+-------------+----------+
| 2 | 1-15-2016 00:35:00 | 19 | 41 |
+----+--------------------+-------------+----------+
| 3 | 1-15-2016 00:40:00 | 20 | 40 |
+----+--------------------+-------------+----------+
| 4 | 1-15-2016 00:45:00 | 20 | 42 |
+----+--------------------+-------------+----------+
| 5 | 1-15-2016 00:50:00 | 21 | 42 |
+----+--------------------+-------------+----------+
| 6 | 1-15-2016 00:55:00 | 20 | 43 |
+----+--------------------+-------------+----------+
| 7 | 1-15-2016 01:00:00 | 21 | 43 |
+====+====================+=============+==========+
Let's say, I always want two data points (in reality a lot more). So for the last half hour I want the database to return data point 1 and 4, for the last ten minutes I want it to return 6 and 7.
Thanks for helping!
PS: I'm sorry for any errors in my English
OK, assuming a very simple systematic approach, you can get the first and last entry for any defined period:
select *
from table
where mydatetime =
(select
max(mydatetime)
from table
where mydatetime between '2017-03-01' and '2017-03-15'
)
OR mydatetime =
(select
min(mydatetime)
from table
where mydatetime between '2017-03-01' and '2017-03-15'
)
I believe your answer can be found at the following location:
https://stackoverflow.com/a/1891796/7176046
If you are looking to filter out any items not within your date/time your query would use:
Select * from table where Date/Time is (What you want to sort by)

Mysql timestampdiff sum between overlapped intervals

I have the following table structure:
+----+---------------------+---------------------+
| id | created_at | closed |
+----+---------------------+---------------------+
| 1 | 2017-04-03 04:00:00 | 2017-04-03 04:30:00 |
| 2 | 2017-04-03 04:25:00 | 2017-04-03 04:35:00 |
+----+---------------------+---------------------+
In my real SQL query I use timestampdiff to clacualte the diffirence between two dates in timestap field. There is no problem if the ctreated_at and closed_at of all records start in diffirent time intervals, so I would able to get time consumed for all rows as follows:
SELECT SUM(timestampdiff(SECOND, created_at, closed_at)) as TotalTime FROM table
My problem is like the shown table above, the time interval crossing. The above query will result 900 but it I should have 600
I have tried something like:
SELECT timestampdiff(
MINUTE,
a.created_at,
(SELECT max(b.closed) from times as b WHERE b.created_at < a.closed)
) as periods
FROM `times` as a
The result is:
+---------+
| periods |
+---------+
| 35 |
| 10 |
+---------+
Here I want only the first result whuch represnts the net time of the overlapped periods. Using MAX with the previous query should returns the first record but it will lead to neglect any other periods groups added in the futere supposed the table becomes:
+----+---------------------+---------------------+
| id | created_at | closed |
+----+---------------------+---------------------+
| 1 | 2017-04-03 04:00:00 | 2017-04-03 04:30:00 |
| 2 | 2017-04-03 04:25:00 | 2017-04-03 04:35:00 |
| 3 | 2017-04-03 05:00:00 | 2017-04-03 05:15:00 |
+----+---------------------+---------------------+
the above query returns:
+---------+
| periods |
+---------+
| 35 |
| 10 |
| 15 |
+---------+
Again here I don't want the second record because it describes its period which is previously counted in the first record. Indeed I don't know does it possible in MySQL to get (for the example above) only two records or even three records but the second is null, 0, negative value, etc to be distinguished among other really values.
You need to do group by the time on hourly basis and the take difference time for of max.
SELECT max(timestampdiff(
MINUTE,
a.created_at,closed) as periods
FROM `times` as a group by hour(created_at)
Now you will get result as per ur requirement.

How to get the expired candidates in MySQL

I am having a table with the columns for expired_date and registered_date.
Expired date have set for 2 days to registered date.
Its look like this:
+--------------+--------------+---------------------+
| candidate_id | date_expires | date_added |
+--------------+--------------+---------------------+
| 1 | 2016-03-26 | 2016-03-24 14:42:18 |
| 2 | 2016-03-23 | 2016-03-21 15:43:40 |
| 3 | 2016-02-15 | 2016-02-13 14:53:30 |
| 4 | 2016-02-22 | 2016-02-20 14:54:19 |
+--------------+--------------+---------------------+
My question is, I want to select expired profile to current date and time.
This is how I tried it, but it doesn't work.
SELECT * FROM candidates WHERE date_added = DATE_ADD(date_added, INTERVAL 2 DAY);
Hope somebody may help me out.
Thank you.
You may try any of the following query which meets your need.
SELECT
*
FROM candidates
WHERE date_expires < CURDATE();
Or if you want to get the expired accounts with respect to date_added field then follow the query given below:
SELECT
*
FROM candidates
WHERE DATE_ADD(date_added, INTERVAL 2 DAY) < CURDATE();
EDIT:
For fine-grained comparison you may use the following query:
SELECT
*
FROM candidates
WHERE TIMESTAMPADD(DAY,2,date_added) < NOW();
Note: Actually you don't need to store the expired dates in database. Rather you can store the profile life time (in this case it is 2 Days) in database if this profile life time varies across different accounts. You don't need to store this in database if it's constant in nature (i.e. Always 2 DAYS).
So if you want to bring this change in your table structure then it would look like below:
+--------------+--------------+---------------------+
| candidate_id | days | date_added |
+--------------+--------------+---------------------+
| 1 | 2 | 2016-03-24 14:42:18 |
| 2 | 5 | 2016-03-21 15:43:40 |
| 3 | 3 | 2016-02-13 14:53:30 |
| 4 | 10 | 2016-02-20 14:54:19 |
+--------------+--------------+---------------------+
You need a modified query for this change.
Here it is:
SELECT
*
FROM candidates
WHERE TIMESTAMPADD(DAY,days,date_added) < NOW();
You're looking for this
SELECT *
FROM candidates
WHERE date_expires < NOW();

SQL query for related rows of data from the same table

I am trying to understand how to write SQL statements which can return related rows of data from the same table.
By way of example, I have the following table called purchases:
------------------------------
|ID | Customer | Date | Cost |
------------------------------
1 | 1 | Mon | 20.0
2 | 1 | Tue | 10.0
3 | 1 | Sat | 23.0
4 | 2 | Thu | 211.0
5 | 2 | Mon | 24.0
6 | 2 | Sat | 50.0
7 | 3 | Mon | 34.0
8 | 3 | Sat | 200.0
9 | 3 | Fri | 90.0
I want the data for how much each customer spent on Saturday and the corresponding data for how much they spent on Monday, so that I would have the following data:
Saturday: [23.0,50.0,200.0]
Monday: [20.0,24,0,34.0]
How do I do this? I can do:
SELECT cost FROM purchases WHERE Date=='Sat' and SELECT cost FROM purchases WHERE Date=='Mon' but this doesn't seem very satisfactory because it depends on the order in which the database gives the result and a purchase may not have happened on both Saturday and Monday.
I investigated Joins and Unions for this purpose but they seem concerned with data from more than one table.
I'm sure there's a standard way to solve this problem.
You could join the table to itself; this would give you the data you want, but in the format
UserID, AmountSpentSat, AmountSpentMon
The SQL:
select p1.Customer, p1.cost as AmountMon, p2.cost as AmountSat
from purchases p1, purchases p2
where p1.customer = p2.customer
and p1.date = "Mon"
and p2.date = "Sat"
Here is a working sqlfiddle of it: http://sqlfiddle.com/#!2/367ef/1
Note I added a new customer (4) who only shopped on Sat and it works correctly.