简体   繁体   English

如何使我的 MySQL 查询更简洁?

[英]How do I make my MySQL query with joins more concise?

I have a huge MySQL query that depends on JOINs.我有一个巨大的 MySQL 查询,它依赖于 JOIN。

SELECT m.id, l.name as location, CONCAT(u.firstName, " ", u.lastName) AS matchee, u.email AS mEmail, u.description AS description, m.time AS meetingTime
FROM matches AS m
LEFT JOIN locations AS l ON locationID=l.id 
LEFT JOIN users AS u ON (u.id=m.user1ID)
WHERE m.user2ID=2

UNION

SELECT m.id, l.name as location, CONCAT(u.firstName, " ", u.lastName) AS matchee, u.email AS mEmail, u.description AS description, m.time AS meetingTime
FROM matches AS m
LEFT JOIN locations AS l ON locationID=l.id 
LEFT JOIN users AS u ON (u.id=m.user2ID)
WHERE m.user1ID=2

The first 3 lines of each sub-statement divided by UNION are identical.除以 UNION 的每个子语句的前 3 行是相同的。 How can I abide by the DRY principle, not repeat those three lines, and make this query more concise?怎样才能遵守DRY原则,不重复那三行,让这个查询更加简洁呢?

Try in this way, should work:以这种方式尝试,应该工作:

SELECT m.id, l.name as location, CONCAT(u.firstName, " ", u.lastName) AS matchee, u.email AS mEmail, u.description AS description, m.time AS meetingTime
FROM matches AS m
LEFT JOIN locations AS l ON locationID=l.id 
LEFT JOIN users AS u 
ON ((u.id=m.user1ID AND m.user2ID=2) OR (u.id=m.user2ID AND  m.user1ID=2))
WHERE (m.user1ID=2 OR m.user2ID=2)
SELECT
  s.id,
  s.location,
  CONCAT(u.firstName, " ", u.lastName) AS matchee,
  u.email AS mEmail,
  u.description AS description,
  s.meetingTime
FROM (
  SELECT
    m.id,
    l.name AS location,
    m.time AS meetingTime,
    CASE m.user1ID when @userID THEN m.user2ID ELSE m.user1ID END AS userID
  FROM matches AS m
  LEFT JOIN locations AS l ON m.locationID = l.id
  WHERE m.user1ID = @userID OR m.user2ID = @userID
) AS s
LEFT JOIN users AS u ON s.userID = u.id

The subquery filters the matches table on the specified user ID, joins it to locations , pulls the necessary columns from the two tables and prepares a single userID column (using either user1ID or user2ID , depending on which of the two is not the specified ID) to joining with users .子查询根据指定的用户 ID 筛选matches表,将其连接到locations ,从两个表中提取必要的列并准备单个userID列(使用user1IDuser2ID ,具体取决于两者中的哪一个不是指定的 ID)加入users The outer query joins the inner SELECT's result set to users and pulls the rest of the columns, obtained as a result of the join.外部查询将内部 SELECT 的结果集连接到users ,并提取作为连接结果获得的列的 rest。

1) I see that you are matching users and you keep some information related to that match. 1)我看到你在匹配用户,你保留了一些与匹配相关的信息。

That's a little complicated to design.设计起来有点复杂。 The easy approach is just make the data in matches redundant.简单的方法就是让 matches 中的数据冗余。 By this way you will always get the match of user1ID=2.通过这种方式,您将始终获得 user1ID=2 的匹配项。 Means you need to store every match for 2 times, in one user1ID and user2ID and in the second with the opposite values of user1ID and user2ID.意味着您需要将每个匹配项存储两次,一次是 user1ID 和 user2ID,第二次是 user1ID 和 user2ID 的相反值。 However as I said this is redundant and if you expect many records I don't recommend it.然而,正如我所说,这是多余的,如果您希望有很多记录,我不推荐它。

2) Other approach is normalizing your design. 2)其他方法是规范化您的设计。 Create another table matchUser(matchId, userId) (primary key is both attrs)再建一张表matchUser(matchId, userId) (主键都是attrs)

SELECT ... FROM matches AS m
LEFT JOIN locations AS l ON locationID=l.id 
LEFT JOIN users AS u ON (u.id=mu2.userId)
INNER JOIN matchUser mu1 ON mu1.userId=2
INNER JOIN matchUser mu2 ON mu2.matchId=mu1.matchId AND mu2.userId != 2

Something like this, the query maybe wrong I didn't test it but you'll get the idea.像这样,查询可能是错误的我没有测试它,但你会明白的。

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

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