Reputation: 1179
I got a table agenda
in which the admin can make a reservation for him self or for someone else (another user). If the admin make the reservation for him self in agenda.user_id
will be stored the id
of admin.
In case that admin make a reservation for another person (another user) in agenda.user_id
will be stored the id
of the user for which the reservation will be made. The id
of the admin will be stored in another column agenda.booked_user
.
All the reservations are stored on agenda_users
table also. agenda_users
has this columns: id
,agenda_id
, user_id
. The agenda_users.user_id
it refers to agenda.user_id
.
I want to retrieve all the reservations made by the admin which has made reservations for himself and for other users also.
I did a query with some AND & OR:
SELECT agenda.*
FROM agenda,agenda_users
WHERE agenda_users.agenda_id=agenda.id
AND (agenda_users.user_id=$user_id
AND agenda_users.user_id=agenda.user_id)
OR (agenda_users.user_id=agenda.user_id
AND agenda.booked_user=agenda.$user_id)
AND checkout IS NULL
AND NOW() < DATE_ADD(date_end, INTERVAL 6 HOUR) ORDER BY type ASC,date_start ASC
Cannot figure out the right solution to 'grab' all the reservations the admin has made for him self and other users.
Upvotes: 0
Views: 91
Reputation: 94859
This is too long for a comment. So I am posting this as an answer and may adjust it, once you clarify doubts about the data model.
There is a parent table agenda
and it has a child table agenda_users
. So one agenda has several users. But the agenda
table itself has two users, too. One is the person who made the reservation, but rather than using one column for that user, you are using sometimes one column and sometimes the other. You say that when an admin makes a reservation for another user, the admin gets stored in the column booked_user
, although it's obviously not the booked user, but the booking user. I wonder whether you have understood the data model yourself, because the explanation sounds just wrong.
Then, an agenda
should typically be identified by its id
(hence the name), so the agenda_users
should be linked via its agenda_id
only. Are you sure that the user_id
of the two tables must match, too? That would mean an agenda.id
is unique only in combination with a user_id
? It is possible, but doesn't seem likely.
Your query has some issues, too.
agenda.$user_id
is probably supposed to mean $user_id
only?AND
has precedence over OR
, so the checkout
and date_end
criteria will only work for the part after OR
.checkout
and date_end
belong to? I assume it's the agenda
table and will write my query accordingly, because you mentioned the columns of the agenda_users
table and these two columns were not among them.You want to select data from agenda
. So, do so; don't join another table. If you have criteria based on the other table, then use IN
or EXISTS
for the lookup. In your case, though, - but I can only guess here - it seems you don't need the agenda_users
table at all.
SELECT *
FROM agenda
WHERE (user_id = $user_id OR booked_user = $user_id)
AND checkout IS NULL
AND NOW() < DATE_ADD(date_end, INTERVAL 6 HOUR)
ORDER BY type, date_start;
Upvotes: 1
Reputation: 14900
solving the old-style-joins will leave you with this SQL:
SELECT agenda.*
FROM agenda
INNER JOIN agenda_users ON agenda_users.user_id=agenda.user_id AND agenda_users.agenda_id=agenda.id
WHERE
(agenda_users.user_id=$user_id) OR (agenda.booked_user=agenda.$user_id)
AND checkout IS NULL
AND NOW() < DATE_ADD(date_end, INTERVAL 6 HOUR) ORDER BY type ASC,date_start ASC;
This SQL is almost human-readable (and understandable). 😉
EDIT: Added extra ()
because AND has higher precedence than OR.
SELECT agenda.*
FROM agenda
INNER JOIN agenda_users ON agenda_users.user_id=agenda.user_id AND agenda_users.agenda_id=agenda.id
WHERE
((agenda_users.user_id=$user_id) OR (agenda.booked_user=agenda.$user_id))
AND checkout IS NULL
AND NOW() < DATE_ADD(date_end, INTERVAL 6 HOUR) ORDER BY type ASC,date_start ASC;
Upvotes: 1
Reputation: 9042
It is cleaner in my opinion to use UNION
instead of a very complex where conditions.
Note that you know the user_id you are filtering for, therefore you don't need to join.
/* The ones for admin created by the user */
SELECT
agenda.*
FROM
agenda A
WHERE
A.user_id = $user_id
UNION ALL
/* the ones where the admin created it, but not for itself */
SELECT
agenda.*
FROM
agenda A
WHERE
A.booked_user_id = $user_id
AND A.user_id <> $user_id
Don't forget to add the rest of the where conditions to both subqueries of the union
Upvotes: 0