MYSQL date compare query - mysql

I'm trying to return a list of vehicles where I know they are not already booked for a current date range. I have a tblVehicles table:
ID Name
1 BMW
2 Merc
3 Land Rover
4 Hummer
5 Convertable
I also have a table (tblDiary) that holds all the dates that vehicle is being used:
ID VehicleId startDate endDate
1 1 2016-06-20 2016-06-22
2 1 2016-06-24 2016-06-24
3 2 2016-05-01 2016-06-05
So I'm trying to write a query where I want to find vehicles that are available between 2016-06-21 & 2016-06-23. So, in this instance the desired result would be:
ID Name
2 Merc
3 Land Rover
4 Hummer
5 Convertable
What the most efficient way of doing this?

SELECT *
FROM tblVehicles v
WHERE NOT EXISTS
(
SELECT NULL
FROM tblDiary d
WHERE d.vehicleId = v.id
AND endDate >= '2016-06-21'
AND startDate <= '2016-06-23'
)

Related

Selectively select column data based on date range in MySQL

Is there a way in MySQL to select specific columns based on dates entered as variables?
For example, if there is a table containing daily data from Day 1 to Day 31 for various items. Like the table below -
id
Month
Year
Item
Day 1
Day 2
Day3
Day 4
Day 5
1
December
2021
Bag
2
4
2
5
1
2
December
2021
Pencil
3
5
1
8
2
This goes up to Day 31 if needed for any number of items in the month.
I'd like to be able to enter a date range such as 2021-12-01 and 2021-12-03 along with the item name 'Bag' and get the sum of the values in that data range - 2+4+2 = 8.
Is this possible?
And if it isn't possible with this current method I'm attempting, is there a way to get it done?
Thanks.
This may not be the answer you want, but you should seriously fix your data model. Do not store your dates as columns, but rather store each date's data point in a separate record. So the first record from your sample table would become:
id | Item | Date | num_items
1 | Bag | 2021-12-01 | 2
1 | Bag | 2021-12-02 | 4
1 | Bag | 2021-12-03 | 2
1 | Bag | 2021-12-04 | 5
1 | Bag | 2021-12-05 | 1
Now your query becomes much more tractable:
SELECT id, Item, SUM(num_items) AS total
FROM yourTable
WHERE Date BETWEEN '2021-12-01' AND '2021-12-03' AND Item = 'Bag'
GROUP BY id, Item;
a bit verbose, but you can do something like this :
SELECT
IF (DAY('2021-12-01') <= 1 AND DAY('2021-12-03') >= 1, day1, 0)
+ IF (DAY('2021-12-01') <= 2 AND DAY('2021-12-03') >= 2, day2, 0)
+ IF (DAY('2021-12-01') <= 3 AND DAY('2021-12-03') >= 3, day3, 0)
+ ...
Although it's probably better to change your data model to have a date and value as column.

How to join to single row in one to many relationship in SQL?

I want to join one to many table with single row on many table by limit 1 and order by create date
tbl_cart :
id fullname
1 myname1
2 myname2
3 myname3
tbl_cart_status:
id cart_id status created_at
1 1 33 2018-09-20
2 1 34 2018-09-23
3 2 34 2018-09-21
4 1 100 2018-09-25
5 2 35 2018-09-29
How can i get output with sql like this:
I want to get lastest status of my cart by ordered with created_at column
myname cart_id status created_at
myname1 1 100 2018-09-25
myname2 2 35 2018-09-29
Think filtering for this type of query:
select c.name, cs.*
from tbl_cart c join
tbl_cart_status cs
on c.id = cs.cart_id
where cs.created_at = (select max(cs2.created_at)
from tbl_cart_status cs2
where cs2.cart_id = cs.cart_id
);

SQL joining on two columns with a variation on the first column

I have two tables:
Table 1: planA
ID Date Count
3 2017-01-01 10
2 2017-02-03 15
10 2017-01-30 8
Table 2: planB
ID Date Value
3 2017-01-02 11
2 2017-02-04 12
21 2017-01-30 3
3 2017-02-03 33
What I want to do is to join the two tables on (ID and Date) columns.
However, on Date, I want to use the next day to the date on the table 1.
Therefore, the joined table should look like the following:
PlanA.ID PlanA.Date PlanB.Date PlanA.Count PlanB.Value
3 2017-01-01 2017-01-02 10 11
2 2017-02-03 2017-02-04 15 12
Is this even possible?
Any suggestion would be appreciated!
Yes it is possible:
select
PlanA.ID,
PlanA.Date,
PlanB.Date,
PlanA.Count,
PlanB.Value
from
PlanA inner join PlanB
on (
PlanA.ID = PlanB.ID
and
PlanA.Date + INTERVAL 1 DAY = PlanB.Date
)
if Date is a column of type date, + INTERVAL 1 DAY will return the next day of the one given, and then you can perform the join.

How to check if records within selected date using multiple tables?

It is an additional question to my previous one that is already answered.
There are 4 tables: buildings, rooms, reservations, information
1 building = n rooms
1 room = n reservations
TABLE BUILDINGS - ID(int), name(varchar)
TABLE ROOMS - ID(int), building_id(int)
TABLE RESERVATIONS - ID(int), room_id(int), date_start(datetime), date_end(datetime)
TABLE INFORMATION - ID(int), building_id(int), hours_start(int), hours_end(int)
Buildings table example
ID name
1 Building A
2 Building B
3 Building C
Rooms table example
ID building_id
1 1
2 1
3 2
4 3
Reservations table example
ID room_id date_start date_end
1 1 2014-08-09 14:00:00 2014-08-09 14:30:00
2 1 2014-08-09 14:30:00 2014-08-09 15:30:00
3 3 2014-08-09 16:30:00 2014-08-09 17:30:00
4 2 2014-08-09 16:00:00 2014-08-09 17:00:00
5 3 2014-08-09 16:00:00 2014-08-09 16:30:00
Information table example
ID building_id hours_start hours_end
1 1 9 22
2 2 8 20
3 3 8 22
Question
Can we filter buildings that has atleast 1 available room on selected date in any hour? Buildings working hours may be different (Information table).
I think this will do what you want. It calculates the total number of meeting hours in the building for all the rooms. It then calculates the total meeting hours. If a room is available the second is less than the first:
SELECT b.id, b.name,
sum(timestampdiff(minute, rv.date_start, rv.date_end))/60 as MeetingHours,
max(hours_end - hours_start)*count(distinct r.id) as BuildingHours
FROM buildings b JOIN
information bi
on b.id = bi.building_id
rooms r
ON b.id = r.building_id LEFT JOIN
reservations rv
ON rv.room_id = r.id AND
'2014-08-09' between date(rv.date_start) AND date(rv.date_end)
GROUP BY b.id
HAVING MeetingHours is Null or MeetingHours < BuildingHours;

MySQL cyclically one row for each valid user

Here's the background, I have a table object containing :
id
user (id from user table)
date (date)
state (0|1)
And another table user containing :
id
state (0|1)
EX.:
Object
ID | USER | DATE | STATE
1 1 2012-10-01 1
2 2 2012-08-01 1
3 3 2012-10-01 1
4 3 2012-10-02 1
5 3 2012-09-01 1
6 3 2012-10-01 1
7 1 2012-10-02 1
8 2 2012-10-02 0
9 2 2012-10-02 1
10 1 2012-10-01 1
11 2 2012-10-01 1
12 3 2012-10-01 0
13 4 2012-11-11 1
Users
ID | STATE
1 | 1
2 | 1
3 | 1
4 | 0
I would make a request to display one object per valid state user cyclically, if object state is active, order by date DESC.
EX. result :
ID | USER | DATE | STATE
10 1 2012-11-01 1
9 2 2012-10-02 1
4 3 2012-10-02 1
7 1 2012-10-02 1
11 2 2012-10-01 1
3 3 2012-10-01 1
1 1 2012-10-01 1
2 2 2012-08-01 1
6 3 2012-10-01 1
5 3 2012-09-01 1
I can do simple queries but then I admit to not knowing how to do here.
EDIT 2012-11-22 :
Let trying another approch... With this query (thanks Michiel van Vaardegem), I have a list of users, in order that I want... the one with freshness object on top.
SELECT o.user
FROM object o
INNER JOIN users ON user.id = o.user
WHERE o.state=1 AND users.state=1
GROUP BY o.user
ORDER BY o.date DESC
Result is :
USER
1
2
3
NEW QUESTION APPROCH :
With this list of ids, the possible calculated count of rows, and user defined vars, do you think something could be done?
Exemple :
Assuming this list, SELECT * FROM object WHERE user IN
($thislist) AND state=1 ORDER BY date DESC
For each object row depending of user (here I don't know how to explain in mysql)
incrementing a rank var with the userposition(in cycle) + usercount
ORDER BY rank LIMIT n,x that result
I whant to rank my objects in a user cycle, like :
object from user 1,2,3,1,2,3,1,3,3,1,1,1,1,1,1,1,1,etc... if exist
Do this new approch algo be realizable in a mysql query, and if possible how... that is the great question?
Can anybody see a solution only in MySQL?
Thanks in advance
Something like:
SELECT o.id, o.user, o.date, 1 AS state
FROM object o
INNER JOIN user ON u.id = o.user
WHERE o.state = 1 AND u.state = 1
GROUP BY o.user, o.date
ORDER BY o.user, o.date DESC
I'm not sure, but if I read it correctly, you only want records where the state in both tables is '1', correct?
And you want to sort first on user and then on the date desc?