Can't query select data when my date is filled - mysql

I have a database structure like this:
and I want to check room type that available at a specific date, so I run this query.
SELECT type.type_name, orders_details.access_date
FROM type
LEFT JOIN rooms ON type.type_id = rooms.room_id
LEFT JOIN orders_details ON rooms.room_id = orders_details.room_id
AND orders_details.access_date BETWEEN "2023-01-19" AND "2023-01-21"
WHERE orders_details.access_date IS NULL
GROUP BY type.type_name
I have several rooms for one type of rooms. I have 3 rooms that have same type id. When one of those rooms in same type is booked, and I run the query, the type is not showing.
How can I still query type even one rooms on of the type is still available?

This part matching type_id with room_id looks illogical.
LEFT JOIN rooms ON type.type_id = rooms.room_id

Related

How to join on a row with max value

I have three tables: households, voters, door_knocks
Each household can have several voters associated with it. Each household can also have several door knocks associated with it.
I'm trying to pull together all the voters in a household and the date of the last door_knock from the door_knocks table and I'm having trouble figuring out the proper query syntax. Here is my latest attempt:
SELECT households.hh_id, voters.id
FROM households
INNER JOIN voters ON households.hh_id = voters.hh_id
INNER JOIN ( SELECT MAX(dk.date), dk.hh_id FROM door_knocks dk GROUP BY dk.date) dks
ON dks.hh_id = households.hh_id
WHERE households.street = ?
The above query pulls up one result for each door knock, however. I just want the the date from the last door knock.
So, what it sounds like you're hoping for conceptually is a table that lists the last date of a knock for each houshold.
You'd like to join against that table and combine it with the voters and the households.
what your query does is give you a table of all the dates (group by dk.date) and for each date list all the households.
If you group by hh_id instead, then you will get the max date for each given household.
SELECT households.hh_id, voters.id, dks.max_date
FROM households
INNER JOIN voters ON households.hh_id = voters.hh_id
INNER JOIN ( SELECT MAX(dk.date) as max_date, dk.hh_id FROM door_knocks dk GROUP BY dk.hh_id dks
ON dks.hh_id = households.hh_id
WHERE households.street = ?

How to count and join between two MySQL tables?

I want to write out the number of times a car has been rented and I just cant get it to work, I have two tables. one is called vehicle and the other rental.
In rental is where all the "rentings" go when you book a car and all the vehicles is stored in vehicle. This is the query I made that almost works.
SELECT vehicle.id,COUNT(rental.vid) as rented,IFNULL(rental.vid,0) as nothing, vehicle.make as make, vehicle.model as model, vehicle.regnr as regnr, vehicle.color as color, vehicle.state as state, vehicle.imgurl as img, vehicle.description as description, vehicle.id
FROM rental,vehicle
WHERE vid = vehicle.id GROUP BY vid
and will print out this:
The rest which doesn't have a value (never been rented) isn't there, I have tried a lot of different ways with IFNULL but haven't gotten anywhere.
Select from Vehicle table and Left Join to Rental table. This will include Vehicle that have never been Rented and their Count(rental.vid) will be 0:
SELECT vehicle.id
,COUNT(rental.vid) as rented
, vehicle.make as make
, vehicle.model as model
, vehicle.regnr as regnr
, vehicle.color as color
, vehicle.state as state
, vehicle.imgurl as img
, vehicle.description as description
FROM vehicle
left join rental on vid = vehicle.id
GROUP BY vehicle.id
Here is a simplified example
The implicit join you have in your example is equivalent to an inner join. With a left join you select all rows you want from your source table. If there are matches to the table you are left joining to, they will appear as well. It's a good way to append data to your source table.

Sql conditional Join on different tables

I've to add a notification module on an existing project.
My table structure is like on the pic.
Picture :
as you see on the picture every notification has a type and a releatedID.
Type 1 = reservation is cancelled, releated ID is the id on "reservations" table
Type 3 = account balance is under the given min. limit so releatedID is the id on "account_movements"
table
what I'm trying to do is a conditional join to avoid 2 different sql queries;
Get all notifications which are belong to the person
Get notification details from different tables based on "notification.Type"
So the question is can I do it in one query ?
Something like the following should work. Basically you specify which records in your notifications table join with records in your reservations table or your account_movements table when you join those in. Use a LEFT JOIN so that ALL of your notification records make it through, and only those records in the reservations table OR the account_movements that have a match make it through.
SELECT
n.id,
n.type,
n.companyid,
n.personid,
n.relatedid,
n.description,
r.details as reservation_details,
am.details as account_movement_details,
COALESCE(r.details, am.details) AS combined_detail
FROM
notifications n
LEFT OUTER JOIN reservations r ON
n.relatedid = r.id AND
n.type = 1
LEFT OUTER JOIN account_movements am ON
n.relatedid = am.id AND
n.type = 3
Here is a SQL FIDDLE with the solution as well.
I added in the COALESCE() just to show that since the JOINS are mutually exclusive, you can safely combine columns from your reservations table and your account_movements table into a single column without fear of missing or duplicating any data.
If you do a left join, you won't have to have any condition :
SELECT * FROM notifications n
LEFT JOIN reservations r ON n.releatedID = r.id
LEFT JOIN account_movements m ON m.releatedID = m.id

"Join" admins of different tables into a string

The real issue
Involved tables and their columns
accounts [id,name]
rooms [id,name,topic,owner]
room_admins [account_id,room_id]
Q: Get all rooms with their admin- and owner ids.
Where "all" of course has a condition to it (above: WHERE name LIKE ...)
Admins and owners should be returned in one column just called "admins". I tried to concatenate them above into one string.
What I tried
I came up with a solution, but it requires the use of an omnious external variable ":room_id" that changes on each outer SELECT and makes therefore no sense at all.
SELECT id,name,topic,
(SELECT GROUP_CONCAT(admins.account_id) AS owner
FROM
(SELECT account_id
FROM `room_admins`
WHERE room_id=:room_id
UNION
SELECT owner FROM `rooms` WHERE id=:room_id) admins) AS owner
FROM `rooms`
WHERE name LIKE "%htm%" OR topic LIKE "%htm%" LIMIT 20
Well, I haven't given this a deep thought... but I've just came up with this (sample data would have been useful to make tests... so this is just a blind answer).
select id, name, topic, group_concat(owner_admin) from (
select id, name, topic, owner owner_admin from rooms
union
select id, name, topic, account_id from rooms
left join room_admins on id = room_id
) s
where name like "%htm%" or topic like "%htm%"
group by id, name, topic
Basically I'm just generating a derived table with owner and admins mixed in one column. Then performing the grouping on that mixed column.
Most of the times, when you want to select and display dependent data, you want to use a JOIN. In this case, you want to join the rooms with their admins, so basically:
SELECT r.id, r.name, r.topic, a.id
FROM rooms r
LEFT JOIN admins a
ON r.id = a.room_id
WHERE :condition
Since you have one additional admin not in the admins table (the room owner), you have to (self) join a second time:
SELECT r.id, r.name, r.topic, a.id
FROM rooms r
LEFT JOIN admins a
ON r.id = a.room_id
LEFT JOIN rooms o
ON r.id = o.id
WHERE :condition
This doesn't give us any new information, but your question states that you want to return the list of admins in a single field. So, finally, putting it all together:
SELECT r.id, r.name, r.topic, GROUP_CONCAT(a.id)
FROM rooms r
LEFT JOIN
(
SELECT id, room_id FROM admins
UNION SELECT room.owner AS id, rooms.id AS room_id FROM rooms
) a
ON r.id = a.room_id
WHERE :condition
GROUP BY r.id
But to avoid this ugly sub-select-union clause, I'd advise you to put the room owner into your admin table too.

join on sub query returns fails

Trying to join a table "fab_qouta.qoutatype" to at value inside a sub query "fab_status_members.statustype" but it returns nothing.
If I join the 2 tables directly in a query the result is correct.
Like this:
select statustype, takst
from
fab_status_members AS sm
join fab_quota as fq
ON fq.quotatype = sm.statustype
So I must be doing something wrong, here the sub query code, any help appreciated
select
ju.id,
name,
statustype,
takst
from jos_users AS ju
join
( SELECT sm.Members AS MemberId, MaxDate , st.statustype
FROM fab_status_type AS st
JOIN fab_status_members AS sm
ON (st.id = sm.statustype) -- tabels are joined
JOIN
( SELECT members, MAX(pr_dato) AS MaxDate -- choose members and Maxdate from
FROM fab_status_members
WHERE pr_dato <= '2011-07-01'
GROUP BY members
)
AS sq
ON (sm.members = sq.members AND sm.pr_dato = sq.MaxDate)
) as TT
ON ju.id = TT.Memberid
join fab_quota as fq
ON fq.quotatype = TT.statustype
GROUP BY id
Guess the problem is in the line: join fab_quota as fq ON fq.quotatype = TT.statustype
But I can't seem to look through it :-(
Best regards
Thomas
It looks like you are joining down to the lowest combination of per member with their respective maximum pr_dato value for given date. I would pull THIS to the FIRST query position instead of being buried, then re-join it to the rest...
select STRAIGHT_JOIN
ju.id,
ju.name,
fst.statustype,
takst
from
( SELECT
members,
MAX(pr_dato) AS MaxDate
FROM
fab_status_members
WHERE
pr_dato <= '2011-07-01'
GROUP BY
members ) MaxDatePerMember
JOIN jos_users ju
on MaxDatePerMember.members = ju.ID
JOIN fab_status_members fsm
on MaxDatePerMember.members = fsm.members
AND MaxDatePerMember.MaxDate = fsm.pr_dato
JOIN fab_status_type fst
on fsm.statustype = fst.id
JOIN fab_quota as fq
on fst.statusType = fq.quotaType
I THINK I have all of what you want, and let me reiterate in simple words what I think you want. Each member can have multiple status entries (via Fab_Status_Members). You are looking for all members and what their MOST RECENT Status is as of a particular date. This is the first query.
From that, whatever users qualify, I'm joining to the user table to get their name info (first join).
Now, back to the complex part. From the first query that determined the most recent date status activity, re-join back to that same table (fab_status_members) and get the actual status code SPECIFIC to the last status date for that member (second join).
From the result of getting the correct STATUS per Member on the max date, you need to get the TYPE of status that code represented (third join to fab_status_type).
And finally, from knowing the fab_status_type, what is its quota type.
You shouldn't need the group by since the first query is grouped by the members ID and will return a single entry per person (UNLESS... its possible to have multiple status types in the same day in the fab_status_members table... unless that is a full date/time field, then you are ok)
Not sure of the "takst" column which table that comes from, but I try to completely qualify the table names (or aliases) they are coming from, buy my guess is its coming from the QuotaType table.
... EDIT from comment...
Sorry, yeah, FQ for the last join. As for it not returning any rows, I would try them one at a time and see where the break is... I would start one at a time... how many from the maxdate query, then add the join to users to make sure same record count returned. Then add the FSM (re-join) for specific member / date activity, THEN into the status type... somewhere along the chain its missing, and the only thing I can think of is a miss on the status type as any member status would have to be associated with one of the users, and it should find back to itself as that's where the max date originated from. I'm GUESSING its somewhere on the join to the status type or the quota.