The matched days count between two dates ranges - mysql

I have two dates for reservation for example I have reservation starts at 2020-03-01
and ends at 2020-04-10.
So when I make select query to know how many days this room has been reserved in the 4th month i want to get count of days 10
Is there anyway to do it in Mysql.
SELECT from_date , to_date
FROM reservations
WHERE room_id = ?
AND from_date >= "2020-04-01" AND to_date >= "2020-04-30"

You can use datediff() andleast()andgreatest()`. I think the logic you want is:
SELECT DATEDIFF(LEAST(to_date, '2020-04-30'),
GREATEST(from_date, '2020-04-01')
) + 1
FROM reservations
WHERE room_id = ? AND
to_date >= '2020-04-01' AND
from_date <= '2020-04-30';
Note that the date logic in the WHERE clause has been modified. This is the correct logic for determining if two time periods overlap. The first ends after the second starts; the first starts before the second ends.

Related

How to select either one row or the other

I have a table with columns VAT, start and end date.
I have two rows. The standard entry has 0000-00-00 as the start and end date and the other row has the start_date 2020-06-01 and the end_date 2020-12-31
I want VAT of the second row to be selected if today's date is between the start and end date, otherwise the standard VAT with 0000-00-00 should be selected
This is my table:
I tried
SELECT *
FROM taxes
WHERE (CASE WHEN start_date < "2020-06-06"
AND end_date > "2020-06-06" THEN 1
ELSE 0
END) = 1
But i don't know how to formulate the else case or whether it can work at all like this
You can use order by and limit for this:
select t.*
from taxes t
where start_date = '0000-00-00' or
'2020-06-06' between start_date and end_date
order by start_date desc
limit 1;
The idea is that the first condition gets the "default" value. The second condition gets the matching condition. These two rows are then sorted, so the matching condition will be first -- if there is one.
There might be ways o doing it with your suggested "0000-00-00' dates for start and end points, but in my view you run a much cleaner ship if you address the time spans individually, i. e. spell out the date ranges for before and after the "exception period", like:
INSERT INTO vat (startdt,enddt,fullrate,reducedrate)
VALUES ('2000-01-01','2020-06-30',.19,.07), -- before
('2020-07-01','2020-12-31',.16,.05), -- exception period
('2021-01-01','2500-12-31',.19,.07); -- after
select * from vat where now() between startdt and enddt;
This way you document in a very clear way which rates were applicable when. And the query itself becomes trivial, see above and check out my demo here: https://rextester.com/YLYUU53617
SELECT *
FROM taxes
WHERE tax_id=IF(start_date < "2020-06-06" AND end_date > "2020-06-06", 1, 0)
you can find the records for current date, then combine this set with the source table filtered by '0000-00-00' excluding country codes from this set
with
current_taxes as (
select *
from taxes
where current_date between start_date and end_date
)
select *
from current_taxes
union all
select *
from taxes
left join current_taxes
using (country_code)
where taxes.start_date='0000-00-00'
and current_taxes.country_code is null
;

Generating monthly report mysql

I have a table in which there are 5 columns,
id (auto incrementing number), titleId, version, created_at
A combination of titleId and version is always unique. I want to find out for each day for the past 1 month, how many unique titleIds were present along with the count of how many entries per day. This is because on a given day there might be multiple versions of the same titleId.
select count(*) from titles where created_at >= '2019-08-12 00:00:00' and created_at <= '2019-08-13 00:00:00' will give me total number of titles which came on 12th August
and
select count(distinct titleId) from titles where created_at >= '2019-08-12 00:00:00' and created_at <= '2019-08-13 00:00:00'
will give me the count of unique titles on the 12th August. Is there a way for me to generate the data for the past 30/60 days?
I know I can run this command manually 30 times by changing the date to get the numbers, but was wondering if there is a better way to do this in mysql
As long as there is an entry every day, this query should give you the data for each day for the last 30:
select date(created_at) as cdate, count(distinct titleId) as cnt
from titles
where created_at >= cur_date() - interval 30 day
group by cdate

Select between dates with count condition

I have table user with column login_time.
I want to select all the users that have logged in more than 10 times in a month.
I tried something like this:
SELECT login_time, count(id) as loginCount FROM user
WHERE login_time between DATE_SUB(login_time INTERVAL 1 month) AND login_time
GROUP BY id, MONTH(login_time) HAVING loginCount > 10;
Im not sure about my selection between dates.
How can I select with a month intervals avoiding double records.
For example if I have this values for login_time:
1. '2015-02-01 14:05:19'
2. '2015-01-21 14:05:19'
3. '2015-01-11 14:05:19'
Both 3 and 2 are within month range of 1.
So will I get double records for that values?
To find the users who have logged in more than ten times in the month ending right now, do this.
SELECT COUNT(*) times_logged_in,
userid
FROM user
WHERE login_time >= NOW() - INTERVAL 1 MONTH
GROUP BY user_id
HAVING COUNT(*)> 10
To find the users who have logged in more than ten times in any calendar month in your table, do this.
SELECT COUNT(*) times_logged_in,
DATE(DATE_FORMAT(login_time, '%Y-%m-01')) month_beginning,
userid
FROM user
GROUP BY user_id, DATE(DATE_FORMAT(login_time, '%Y-%m-01'))
HAVING COUNT(*)> 10
The trick here is the expression DATE(DATE_FORMAT(login_time, '%Y-%m-01')), which converts any timestamp to the first day of the month in which it occurs.
Your question mentioned this WHERE condition:
WHERE login_time between DATE_SUB(login_time INTERVAL 1 month) AND login_time
This doesn't do anything interesting because it always comes back true. Each given login_time always falls in the interval you specified.
Edit: You can GROUP BY MONTH(dt) if you want. But the way I have shown it automatically accounts for years as well as months, so in my opinion it's much better for accurate reporting.
Another edit: This formula yields the preceding Sunday for any given date or timestamp item.
FROM_DAYS(TO_DAYS(login_time) -MOD(TO_DAYS(login_time) -1, 7))
If Monday is the first day of the week in your jurisdiction, change the -1 to -2. Grouping by this function is superior to doing GROUP BY WEEK(login_time) because WEEK() does odd things at the beginnings and ends of calendar years.
This is all written up in more detail here: http://www.plumislandmedia.net/mysql/sql-reporting-time-intervals/

Mysql - Find increased value over a week

Score Table
user_idx (int)
date (datetime)
score (int)
I need to find out how much total score has increased over a week from today's date. I know that I need two of the same user tables grouped by user_idx that one contains total scores from the past to today and the other contains total scores from the past to a date of a week ago.
After that, by substracting one from the other will give me the answer... but I'm struggling to write effective sql query that does it.
I've tried
SELECT BLAH BLAH
FROM (SELECT user_idx, COUNT(*) as last_week_study_amount
FROM user_table
WHERE date <= date_sub(now(),INTERVAL 1 WEEK)
GROUP BY user_idx)
AS a WHERE .....
Could you help me :( ?
Let me clear you want to get total count in last week.
Try below query
SELECT *
FROM (SELECT user_idx, COUNT(*) as last_week_study_amount
FROM user_table
WHERE date <= date_sub(now(),INTERVAL 1 WEEK)
GROUP BY user_idx)
AS a WHERE .....
SELECT (SUM(score) - last_week_score) AS increased_score,
FROM user a
JOIN (SELECT b.user_idx, COUNT(*) as last_week_score
FROM userb
WHERE date<= date_sub(now(),INTERVAL 1 WEEK)
GROUP BY b.user_idx) As c ON a.user_idx = c.user_idx
WHERE DATE(date) <= DATE(NOW())
GROUP BY a.user_idx
I ended up writing this code and I think this one is working okay... not sure if it's the best or has a critical error. I will update it if it turns out to be a bad one...

Operation With SQL and Date

I'm a newbye in the operation with SQL on date.
However,I need to do a query that return record filter by X date < or > of 30 days or similar.
I have this query for now:
SELECT nome_prodotto,quantita
FROM prodotti
LEFT JOIN acquisti
ON prodotti.id_prodotto = acquisti.id_prodotto
my goal is get the product that aren't bought in last 30 days or similar
WHERE DATE_SUB(CURDATE(),INTERVAL 30 DAY) =< your_date;
If the date field in acquisti is called date_acquisti, products not bought in the last 30 days will be queried like this:
SELECT nome_prodotto,quantita
FROM prodotti
LEFT JOIN acquisti
ON (prodotti.id_prodotto = acquisti.id_prodotto
AND acquisti.date_acquisti > CURDATE() - INTERVAL 30 DAY)
where acquisti.id_prodotto is NULL
The trick is using the JOIN condition to get only the product acquisitions in the last 30 days. Since this is a LEFT JOIN, any row in result set where acquisti.id_prodotto is NULL means the product was not purchased in that period.
You can use date_add function to achieve this
Ex:
x_date between DATE_ADD(NOW(), INTERVAL -1 MONTH) and NOW()
Also,
where myDate between some_date and some_other_date
may help you in other similar situations.