简体   繁体   English

具有多个 AND & OR 条件的 Where 子句

[英]Where clause with multi AND & OR conditions

I got a table agenda in which the admin can make a reservation for him self or for someone else (another user).我有一个表格agenda ,管理员可以在其中为他自己或其他人(另一个用户)进行预订。 If the admin make the reservation for him self in agenda.user_id will be stored the id of admin.如果管理员在议程中为他自己预订, agenda.user_id将存储管理员的id

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.如果管理员在议程中为另一个人(另一个用户)进行预订agenda.user_id将存储将为其进行预订的用户的id The id of the admin will be stored in another column agenda.booked_user .管理员的id将存储在另一个列中agenda.booked_user

All the reservations are stored on agenda_users table also.所有预订也存储在agenda_users表中。 agenda_users has this columns: id , agenda_id , user_id . agenda_users有这些列: idagenda_id ID ,用户user_id The agenda_users.user_id it refers to agenda.user_id . agenda_users.user_id它指的是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:我用一些 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.无法找出正确的解决方案来“获取”管理员为他自己和其他用户所做的所有预订。

solving the old-style-joins will leave you with this SQL:解决旧式连接会给你留下这个 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).这个 SQL 几乎是人类可读的(并且可以理解)。

EDIT: Added extra () because AND has higher precedence than OR.编辑:添加了额外的() ,因为 AND 的优先级高于 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;

It is cleaner in my opinion to use UNION instead of a very complex where conditions.在我看来,使用UNION而不是非常复杂的 where 条件更简洁。

Note that you know the user_id you are filtering for, therefore you don't need to join.请注意,您知道要过滤的 user_id,因此您不需要加入。

/* 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不要忘记将 where 条件的 rest 添加到并集的两个子查询中

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.因此,一旦您澄清对数据 model 的疑问,我将其发布为答案并可能会对其进行调整。

There is a parent table agenda and it has a child table agenda_users .有一个父表agenda ,它有一个子表agenda_users So one agenda has several users.所以一个议程有几个用户。 But the agenda table itself has two users, too.但是agenda表本身也有两个用户。 One is the person who made the reservation, but rather than using one column for that user, you are song 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.您说当管理员为另一个用户进行预订时,管理员将存储在列booked_user中,尽管显然不是预订用户,而是预订用户。 I wonder whether you have understoodthe data model yourself, because the explanation sounds just wrong.我不知道您是否自己理解了数据model,因为解释听起来很错误。

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.然后, agenda通常应由其id (因此名称),因此agenda_users应仅通过其agenda_id ID 链接。 Are you sure that the user_id of the two tables must match, too?您确定两个表的user_id也必须匹配吗? That would mean an agenda.id is unique only in combination with a user_id ?这意味着一个agenda.id仅与一个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? agenda.$user_id可能应该只表示$user_id
  • The parentheses are probably wrong, too, as AND has precedence over OR , so the checkout and date_end criteria will only works for the part after OR .括号也可能是错误的,因为AND优先于OR ,因此checkoutdate_end标准仅适用于OR之后的部分。
  • Then you are mising qualifiers.那你就错过了预选赛。 This doesn't make the query wrng, but makes it more difficult to read.这不会使查询出错,但会使其更难阅读。 What table do checkout and date_end belong to? checkoutdate_end属于什么表? 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 columns were not mentioned.我假设它是agenda表,并将相应地编写我的查询,因为您提到了agenda_users表的列,而这些列没有被提及。

You want to select data from agenda .您想从agenda中获取 select 数据。 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.如果您有基于其他表的条件,则使用INEXISTS进行查找。 In your case, though, - but I can only guess here - it seems you don't need the agenda_users table at all.但是,就您而言,-但我只能在这里猜测-您似乎根本不需要agenda_users表。

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;

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM