【问题标题】:Always display the left of the join and display the right only if any and if it matches a clause [duplicate]始终显示连接的左侧,仅在有连接且与子句匹配时才显示右侧 [重复]
【发布时间】:2018-02-08 12:26:12
【问题描述】:

我有 3 个表,一个 client 表,一个 user 表和一个 user_has_client 表。

user_has_client 表用于加入其他 2 个表,但它也有一个 roles 列。

MariaDB [extrapack]> desc user;
+----------------+----------------------+------+-----+---------+----------------+
| Field          | Type                 | Null | Key | Default | Extra          |
+----------------+----------------------+------+-----+---------+----------------+
| user_id        | int(10) unsigned     | NO   | PRI | NULL    | auto_increment |
| email          | varchar(255)         | NO   | UNI | NULL    |                |

MariaDB [extrapack]> desc client;
+-------------+------------------+------+-----+---------+----------------+
| Field       | Type             | Null | Key | Default | Extra          |
+-------------+------------------+------+-----+---------+----------------+
| client_id   | int(10) unsigned | NO   | PRI | NULL    | auto_increment |

MariaDB [extrapack]> desc user_has_client;
+-----------+------------------+------+-----+---------+-------+
| Field     | Type             | Null | Key | Default | Extra |
+-----------+------------------+------+-----+---------+-------+
| user_id   | int(10) unsigned | NO   | PRI | NULL    |       |
| client_id | int(10) unsigned | NO   | PRI | NULL    |       |
| roles     | tinytext         | YES  |     | NULL    |       |
+-----------+------------------+------+-----+---------+-------+

clientuser 可能有多个不同的rolesroles 列是一个数组。

MariaDB [extrapack]> select * from user_has_client where roles != "" limit 3;
+---------+-----------+---------+
| user_id | client_id | roles   |
+---------+-----------+---------+
|     181 |       395 | cpa, ce |
|     181 |       473 | cpa     |
|     181 |       498 | cpa     |
+---------+-----------+---------+

但是一个客户只能为一个用户提供一个相同的角色。例如,同一客户端上不能有两个不同的用户拥有cpa 角色。

我想列出一个客户,对于该客户,如果有这样的用户,则只列出一个具有cpa 角色的用户。

这是我的声明:

SELECT c.client_id AS client_id0, ou.user_id AS user_id3, ou.email AS email5 FROM client c LEFT JOIN user_has_client ouhc ON c.client_id = ouhc.client_id LEFT JOIN user ou ON ouhc.user_id = ou.user_id AND ouhc.roles LIKE '%cpa%' WHERE c.client_id = 265 ORDER BY ou.email DESC;

clientuser 可能有也可能没有加入记录,但即便如此,我仍然想显示client 的列表行,所以我无法进行内部连接并拥有进行左连接。

但是在进行左连接时,我仍然希望每个客户端只有一个列表行。

截至目前,上述语句为我提供了客户端的n 行,因为n 用户已加入此客户端。但是这些n 用户中只有一个在其加入中具有cpa 角色。所以我只想显示一个列表行,并与该用户一起显示。

所以,总而言之,我总是希望每个客户端一行,并且只需要一行,并且对于给定角色的用户来说,如果该客户端有 cpa 角色的话。

【问题讨论】:

  • 唯一索引是在用户 ID - 角色字段还是客户端 ID - 角色组合上,问题并不完全清楚。 But one client can offer only one same role to one user. For example, there cannot be one same user having the cpa role on two different clients.引用的句子不清楚,示例不适用于引用的第1句。
  • 引用的第二句确实是错误的。我的错。我将在问题中纠正它。它应该是For example, there cannot be two different users having the cpa role on one same client.
  • 我改写了问题标题,以便更好地关注实际问题。
  • 如果左连接是这里的主要问题,那么这个问题是重复的。
  • @Shadow 从问题的 MySQL 语句中可以看出,我已经应用了现有重复问题中显示的相同解决方案,即在 @ 后面加上 AND 的子句加入的987654346@:LEFT JOIN user ou ON ouhc.user_id = ou.user_id AND ouhc.roles LIKE '%cpa%' 。但是当我需要它只显示一个时它仍然显示很多行。在旁注中,我认为现有的重复问题具有误导性,因为应用了位于 ON 子句中的 WHERE 子句,而不是 before,但仅适用于与联接匹配的那些记录,而不是其他记录。

标签: mysql join


【解决方案1】:

我可能会稍微改变你的计划。使user_has_client.roles 每行只携带一个角色。然后,如果您只想为每个客户端允许一个角色,请在 user_idrole 上设置一个 UNIQUE 约束。

【讨论】:

  • 我不能只拥有一个角色而不是一组角色。这些角色的独特性对我的问题没有副作用。即使角色列中只包含一个角色,问题仍然存在。我会使用= 而不是like,但这不会改变我的选择语句问题。我想。
  • @Stephane Daniel 不建议您为每个用户设置一个角色。他建议 - 非常正确 - 每个用户 - 客户 - 角色安排都应该存储在自己的记录中。这样,您可以通过唯一键强制执行您描述的唯一性。
  • 每行只携带一个角色会产生更多的连接记录。它可能更清晰,因为更明确。但我在一个遗留模式上,不能接触太多。将角色全部放在一列中可以避免破坏现有代码。无论如何,我的问题根本不是关于强制唯一性。如果你去掉多角色方面,只考虑“cpa”的一个可能角色,我的问题仍然存在。
猜你喜欢
  • 2022-12-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-12-18
  • 1970-01-01
  • 2011-06-09
  • 1970-01-01
相关资源
最近更新 更多