Select category between two date in mysql - mysql

I have this Table in mysql. I want to select data as "rc_type" between "start_date" & "end_date".
+----+--------+------------+------------+
| id | rc_type| start_date | end_date |
+----+--------+------------+------------+
| 1 | Gold | 16-05-2016 | 22-05-2016 |
| 2 | Silver | 20-05-2016 | 29-05-2016 |
+----+--------+------------+------------+
My html form has these three fields. So how to find rc_type?
I've tried this query:
SELECT * FROM room_inventory WHERE rc_type='silver' BETWEEN '16-05-2016' AND '17-05-2016'
And also:
SELECT * FROM room_inventory WHERE start_date >= '16-05-2016' AND end_date <= '17-05-2016' AND rc_type='Gold'
If I select start date as 16-05-2016 and end date as 17-05-2016 with "silver" category selection, I got result with "Gold" category. Actually there is no silver type between this two dates.
I don't get proper data. Kindly Help to get proper Data.

You need to separate presentation from real data type, i.e. is better to convert your date columns to real date format instead of varchar. However in order to get proper result you need to convert there strings to proper dates:
SELECT
*
FROM
room_inventory
WHERE
rc_type = 'Silver'
AND STR_TO_DATE(start_date, '%d-%m-%Y') > STR_TO_DATE('15-05-2016', '%d-%m-%Y')
AND STR_TO_DATE(end_date, '%d-%m-%Y') < STR_TO_DATE('30-05-2016', '%d-%m-%Y');
Output:
+----+---------+------------+------------+
| id | rc_type | start_date | end_date |
+----+---------+------------+------------+
| 2 | Silver | 20-05-2016 | 29-05-2016 |
+----+---------+------------+------------+
1 row in set
If you don't do such converts, you will get incorrect results as follow (I have changed Silver's end date to 29-06-2016):
Input:
mysql> select * from room_inventory;
+----+---------+------------+------------+
| id | rc_type | start_date | end_date |
+----+---------+------------+------------+
| 1 | Gold | 16-05-2016 | 22-05-2016 |
| 2 | Silver | 20-05-2016 | 29-06-2016 |
+----+---------+------------+------------+
2 rows in set
Query:
SELECT
*
FROM
room_inventory
WHERE
rc_type = 'Silver'
AND start_date > '15-05-2016'
AND end_date < '30-05-2016';
Output (wrong):
+----+---------+------------+------------+
| id | rc_type | start_date | end_date |
+----+---------+------------+------------+
| 2 | Silver | 20-05-2016 | 29-06-2016 |
+----+---------+------------+------------+
1 row in set
This is because MySQL performs char-by-char comparison and decides that 29-06-2016 < 30-05-2016 which is wrong. So in general you will have further problems if you keep dates columns in varchar format.

you are using wrong date format,
correct is year-month-day
also you had missing the date column in your query, in this example the query search silver category where start date between 2016-06-16 and 2016-05-17
SELECT * FROM room_inventory WHERE rc_type='silver' BETWEEN '2016-05-16' AND '2016-05-17'

#Danilo mentioned you are using wrong date format,
Another thing is your query formate of comparing date syntax is wrong.
correct syntax:
SELECT * FROM room_inventory WHERE rc_type='silver' AND Your Date BETWEEN '2016-05-16' AND '2016-05-17'.
But here you are comparing two dates so this query won't work as your expectation.
With second query please correct your date format as:
'SELECT * FROM room_inventory WHERE start_date >= '2016-05-16' AND end_date <= '2016-05-17' AND rc_type = 'Gold''

There is no need of 'between' try this:
SELECT * FROM room_inventory WHERE rc_type='silver' AND start_date = '16-05-2016' AND end_date = '17-05-2016'

Logical error , You are use between for two columns in a table. between is used to compare in between one columns ,so you can use AND instead of between .
SELECT * FROM room_inventory WHERE rc_type='silver' AND start_date = '16-05-2016' AND end_date = '17-05-2016'

Related

Mysql Subtract 'N' days to date value and compare to current date. N and Date are two column values

My table contains remind_me_befor_days column and expiry_date column.
I have to select records with condition (expiry_date - remind_me_befor_days) = current_date.
How this possible by query. Anyone can help me ?
Thanks in advance
You can do date arithemtics:
select t.*
from mytable t
where t.expiry_date - interval t.remind_me_befor_days day = current_date
Demo on DB Fiddle:
-- sample data
select * from mytable;
id | expiry_date | remind_me_befor_days
-: | :---------- | -------------------:
1 | 2019-12-25 | 10
2 | 2019-12-25 | 5
-- query
select t.*, current_date
from mytable t
where t.expiry_date - interval t.remind_me_befor_days day = current_date
id | expiry_date | remind_me_befor_days | current_date
-: | :---------- | -------------------: | :-----------
1 | 2019-12-25 | 10 | 2019-12-15
To split this into a few subproblems, we have:
Find the current date.
Subtract your remind_me_befor_days column value from the expiry_date column.
Use that as a filter for the records you want from the table.
The first can be done using the MySQL CURDATE() function. Read more here. Combining that with the second and third steps, you get something that looks like
SELECT *
FROM my_table
WHERE expiry_date - remind_me_befor_days = CURDATE()
I would strongly recommend that you write the condition as:
where expiry_date = curdate() + interval remind_me_before_days day
This is index friendly, so it can make use of an index on expiry_date.

How to get multiple records one record using query in mysql

How to be able to query from this data:
parking_place | number_of_month | from_date | end_date | monthly_unit_price
A | 3 | 2018-01 | 2018-03 | 3000000
Desire to show results:
parking_place | month | monthly_unit_price
A | 2018-01 | 3000000
A | 2018-02 | 3000000
A | 2018-03 | 3000000
please suggest me how to query?
You may join using a calendar table:
SELECT
t.parking_place,
t.month,
t.monthly_unit_price
FROM
(
SELECT '2018-01' AS month UNION ALL
SELECT '2018-02' UNION ALL
SELECT '2018-03'
) months
INNER JOIN yourTable t
ON months.month BETWEEN t.from_date AND t.end_date
ORDER BY
months.month;
Note that it would be better to store actual valid date literals to represent each month. For example, instead of storing the text '2018-01', you could store 2018-01-01 as a date literal.

MYSQL Select row when first part of condition is valid (with a group by)

I really don't know how to find an answer for my question, so I'm asking you.
Here is the table I have :
+----+------------+------------+-------------+
| id | start_date | end_date | id_person |
+----+------------+------------+-------------+
| 1 | 2017-10-01 | 2017-12-01 | 1 |
| 2 | 2017-07-01 | 2017-09-01 | 1 |
| 3 | 2016-01-01 | 2016-02-01 | 1 |
| 4 | 2016-05-01 | 2016-06-01 | 2 |
| 5 | 2016-01-01 | 2016-02-01 | 2 |
+----+------------+------------+-------------+
And here is the query I tried to use :
SELECT * FROM table
WHERE ((start_date < NOW() AND end_date > NOW())
OR start_date > NOW()
OR end_date < NOW())
GROUP BY `id_person`
The result I was expecting was this one :
+----+------------+------------+-------------+
| id | start_date | end_date | id_person |
+----+------------+------------+-------------+
| 2 | 2017-07-01 | 2017-09-01 | 1 | // matches first condition
| 4 | 2016-05-01 | 2016-06-01 | 2 | // matches 3rd condition and has the most recent start_date
+----+------------+------------+-------------+
If you didn't get what I did wrong yet, I'm going to tell you.
Here, I was trying to show a single row per person but I wanted this row to match the first condition it finds and not the others, I don't want the row to just be ordered by start_date. It is like a custom order where I want the first row for each person.
The problem is that this query doesn't work since the GROUP BY statement doesn't apply conditions first. (even if it did, I'm not sure the condition would only select one row)
I really don't know how I can achieve that and I don't even know if it is possible, I hope someone can lead me towards any solution.
Thanks for reading this, I'll answer as fast as I can to give you more informations.
Here's one idea...
SELECT m.*
FROM my_table m
JOIN
( SELECT x.id_person
, MAX(x.start_date) start_date
FROM my_table x
JOIN
( SELECT id_person
, MIN(CASE WHEN NOW() BETWEEN start_date AND end_date THEN 'A' WHEN start_date > NOW() THEN 'B' WHEN end_date < NOW() THEN 'C' END) rule
FROM my_table
GROUP
BY id_person
) y
ON y.id_person = x.id_person
AND y.rule = CASE WHEN NOW() BETWEEN start_date AND end_date THEN 'A' WHEN start_date > NOW() THEN 'B' WHEN end_date < NOW() THEN 'C' END
GROUP
BY id_person
) n
ON n.id_person = m.id_person
AND n.start_date = m.start_date;
+----+------------+------------+-----------+
| id | start_date | end_date | id_person |
+----+------------+------------+-----------+
| 2 | 2017-07-01 | 2017-09-01 | 1 |
| 4 | 2016-05-01 | 2016-06-01 | 2 |
+----+------------+------------+-----------+
If are happy to write the rules directly in sql rather than as where conditions you can ask the database for what yuo want more directly.
This means taking a step back to see what the rules you want are. It looks like you want to prioritise the entries by closest date, showing first current, then future, then historical. It also looks like end_date >= start_date, which means you only need to look at end_date to find what you are looking for.
Mysql can answer the question abusing it's group by functionality (until recent versions).
SELECT t.* FROM
(
SELECT t.*
FROM table t
ORDER BY SIGN(t.end_date - NOW()),ABS(t.end_date-NOW())
)
GROUP BY t.id_person
A standard sql method that will also play better with indexes would be to look for end dates before and after today separately.
SELECT t.*
FROM table t
JOIN (
SELECT t.person_id
,COALESCE(first_not_ended.end_date,t.last_ended.end_date) AS end_date
FROM table t
LEFT JOIN (
SELECT t.*,MIN(end_date) AS end_date
FROM table t
WHERE t.end_date > NOW()
GROUP by t.person_id
) first_not_ended
ON t.person_id=first_not_ended.person_id
AND t.end_date=first_not_ended.end_ate
LEFT JOIN (
SELECT t.person_id,MAX(end_date) AS end_date
FROM table t
WHERE t.end_date < NOW()
GROUP by t.person_id
) last_ended
ON t.person_id=last_ended.person_id
AND t.end_date=last_ended.end_date
) closest
ON t.person_id=closest.person_id
AND t.end_date=closest.end_date

SQL Select data between date and hour in two columns

I have a SQL column like this:
| id | name | date | hour |
I want to select all names between specified start_date, start_hour and end_date, end_hour.
For data like this:
| 1 | one | 2014-12-29 | 11:00 |
| 2 | two | 2014-12-30 | 09:00 |
| 3 | three | 2014-12-30 | 11:00 |
Values:
start_date = 2014-12-29
start_hour = 11:00
end_date = 2014-12-30
end_hour = 10:00`
It should return: one, two.
This looks like a basic sql query. try the following:
select a.name
from (select * from data_table
where date >= start_date
and date <= end_date) as a
where a.hour >= start_hour
and a.hour <= end_hour
the basic idea is to first form a data set of all valid days for all times and then from there pull out the valid times. The other possibly more direct method would be to create a datetime field and then pull on that key.
Let me know if this works for you.
SELECT *
FROM table
WHERE date > '2014-12-28'
AND hour > '10:59'
AND date < '2014-12-31'
AND hour < '10:01'

Mysql: converting date fro 'dd/mm/yyyy' to 'yyyymmdd'

Im working on a database that store dates in a varchar(10) mysql field (so sad).
I can not alter the database structure (im building a small plug-in), but i have to query the database finding rows where this data field is between the next 10 days.
Example:
| fid | fdate |
| 1 | 10/09/2010 |
| 2 | 17/09/2010 |
| 3 | 19/09/2010 |
I have to get the rows with fid 1 and 2, becose the date is <= now + 10 days.
Usually i make this kind of query:
SELECT fid FROM table WHERE fdate <= DATE_ADD(NOW(), INTERVAL 10 DAY);
Or, if the date is in the format `yyyymmdd':
SELECT fid FROM table WHERE fdate <= DATE_FORMAT(NOW(), '%Y%m%d');
But theyre useless with the format dd/mm/yyyy.
I've figured out with
SELECT fid, CONCAT(SUBSTRING(fdate, 7, 4), SUBSTRING(fdate, 4, 2), SUBSTRING(fdate, 1, 2)) AS mydate FROM table HAVING mydate <= DATE_ADD(NOW(), INTERVAL 10 DAY);
but i guess it is a bit an overkill rebuilding the date format with concat and substring, and the having clause wont help the query speed.
Any idea?
EDIT
After Adriano's comment, the right solution is
SELECT fid FROM test WHERE STR_TO_DATE(fdate, '%d/%m/%Y') <= DATE_ADD(NOW(), INTERVAL 10 DAY);
so i can avoid the concat and having clause.
What about using str_to_date() to create a date from your format?
EDIT after reading your comment, I created a table like yours:
mysql> SELECT fid, fdate FROM test;
+------+------------+
| fid | fdate |
+------+------------+
| 1 | 10/9/2010 |
| 2 | 17/9/2010 |
| 3 | 19/09/2010 |
+------+------------+
and then did
mysql> SELECT fid FROM test WHERE STR_TO_DATE(fdate, '%d/%m/%Y') <= DATE_ADD(NOW(), INTERVAL 10 DAY);
+------+
| fid |
+------+
| 1 |
| 2 |
+------+
Seems to work. What exactly do you get?