mysql - 我有一个与数据库中大多数其他表相关的表。将其添加为联接是否足以使查询按预期返回?

标签 mysql relational-database

这是数据库的当前结构

企业登录

客户可以是每个公司都有相关信息的预定客户列表中的任何人。 个人资料是他们可以用来访问客户信息的登录帐户。

当某人登录其个人资料时,只要拥有有关客户的有效信息(姓名等),他们就可以将一个或多个客户帐户添加到其个人资料中

这并不常见,但有时一个客户会属于多个配置文件。

客户:

+------------------+--------------------------+-----------+------------+-----+
| id (primary key) | company_id (primary key) | firstname | lastname   | ... |
+------------------+--------------------------+-----------+------------+-----+
|               1  |                        1 | John      | Doe        | ... |
+----------------------------------------------------------------------------+
|               2  |                        1 | Jane      | Doe        | ... |
+----------------------------------------------------------------------------+
|               3  |                        2 | Elmo      | Mack       | ... |
+----------------------------------------------------------------------------+
|               1  |                        2 | Chester   | Torain     | ... |
+----------------------------------------------------------------------------+

个人资料:

+------------------+--------------------------+-----------+-------------+-----+
| id (primary key) | company_id (primary key) | username  | email       | ... |
+------------------+--------------------------+-----------+-------------+-----+
|               1  |                        1 | odoe      | j@gmail.com | ... |
+-----------------------------------------------------------------------------+
|               2  |                        1 | adoe      | d@gmail.com | ... |
+-----------------------------------------------------------------------------+
|               3  |                        2 | emlo      | e@gmail.com | ... |
+-----------------------------------------------------------------------------+
|               1  |                        2 | ches      | c@gmail.com | ... |
+-----------------------------------------------------------------------------+

(枢轴)客户个人资料:

+------------------+-------------+-------------+
| id (primary key) | customer_id | profile_id  |
+------------------+-------------+-------------+
|               1  |          1  |           1 |
+----------------------------------------------+
|               2  |          1  |           2 |
+----------------------------------------------+
|               3  |          3  |           3 |
+----------------------------------------------+

客户和个人资料之间存在多对多关系。 一个客户可以有多个配置文件,每个配置文件可用于访问一个或多个客户,因此需要数据透视表。

客户表和个人资料表都有复合键(id 和 company_id),以保持记录的唯一性 因为数据的传入方式。

还有一个公司表

公司:

+------------------+---------------+------+
| id (primary key) | company_name  | ...  |
+------------------+---------------+------+
|               1  |        google | ...  |
+-----------------------------------------+
|               2  |         yahoo |  ... |
+-----------------------------------------+

公司表与客户表具有一对多关系,与个人资料表具有一对多关系。

作为旁注,数据库中有更多表都具有相同的复合键结构。

问题

如果我进行正常查询

SELECT
    c.`firstname`
,   c.`lastname`
,   p.`username`
,   p.`email`
FROM
    `customer` c
LEFT JOIN `customer_profile` cp ON (cp.`customer_id` = c.`id`)
LEFT JOIN `profile` p ON  (p.`id` = cp.`profile_id`)
WHERE  c.`id` = 1 AND c.`company_id` = 1;

我最终会得到不正确的关系,其中客户 1 公司 1 (John Doe) 将拥有其个人资料和客户 1 公司 2 (Chesters) 个人资料的记录,因为数据透视表不考虑公司 ID

所需的结果是客户的(名字、姓氏)以及与该客户关联的所有个人资料的(用户名和电子邮件)。

给出这些数据后,这就是期望的结果:

+-------------+------------+-----------+--------------+
| firstname   | lastname   | username  | email        |
+-------------+------------+-----------+--------------+
| John        | Doe        | odoe      | j@gmail.com  |
+-----------------------------------------------------+
| John        | Doe        | adoe      | d@gmail.com  |
+-----------------------------------------------------+

实际结果可能包含其他记录,其中数据透视表添加了不应添加的关系。

但实际结果还包含:

+-------------+------------+-----------+--------------+
| firstname   | lastname   | username  | email        |
+-------------+------------+-----------+--------------+
| John        | Doe        | odoe      | j@gmail.com  |
+-----------------------------------------------------+
| John        | Doe        | adoe      | d@gmail.com  |
+-----------------------------------------------------+
| John        | Doe        | ches      | c@gmail.com  |  <--
+-----------------------------------------------------+

我需要过滤掉像这样的个人资料和客户属于不同公司的记录。

为了解决这个问题,我尝试了这个查询

SELECT
    c.`firstname`
,   c.`lastname`
,   p.`username`
,   p.`email`
FROM
    `customer` c
LEFT JOIN `customer_profile` cp ON (cp.`customer_id` = c.`id`)
LEFT JOIN `profile` p ON  (c.`company_id` = p.`company_id` AND p.`id` = cp.`profile_id`)
WHERE  c.`id` = 1 AND c.`company_id` = 1;

这确实给出了所需的结果,因为它也通过 company_id 键加入 这就是我们目前正在使用的,我无法判断它是否适用于所有情况,但它还没有引起任何意外的结果。

问题

我的主要问题是我不知道如何处理公司表。 如果不是我目前所拥有的,将公司表连接到客户表足以删除任何不需要的记录?

类似这样的吗?

SELECT
    c.`firstname`
,   c.`lastname`
,   p.`username`
,   p.`email`
FROM
    `company` co
LEFT JOIN `customer` c ON co.`id` = c.`company_id`
LEFT JOIN `customer_profile` cp ON (cp.`customer_id` = c.`id`)
LEFT JOIN `profile` p ON p.`id` = cp.`profile_id`
WHERE c.`id` = 1 AND c.company_id = 1;

似乎不会,因为数据透视表没有 company_id 记录。

此外,如果能帮助我找到像我这样的另一种情况,我可以引用或做笔记,我们将非常感激。

编辑

将查询 where 子句更改为按 customer.id 而不是按名字搜索,并将 ' 更改为 ` 这才是 wuery 应该有的样子。

如果问题实际上出在数据库的设计上,那没关系,我只需要知道。使用当前的设计会更简单,但如果这就是问题所在,那就是了。 从“philipxy”评论中我可以看出,问题在于数据透视表上没有 company_id 字段。

编辑

查询背后的逻辑是这样的

当该公司的该客户 (c.id AND c.company_id) 拥有该公司的个人资料时,获取姓名和个人资料详细信息。

最佳答案

最终我认为我的问题源于糟糕的数据库设计。我最终为每个表添加了一个新的唯一主键

在客户 table 上就像这样:

+-----+-------------+------------------------+-------------+-----+
| id  | customer_id | company_id | username  | email       | ... |
+-----+-------------+------------+-----------+-------------+-----+
|  1  |           1 |          1 | odoe      | j@gmail.com | ... |
+----------------------------------------------------------------+
|  2  |           2 |          1 | adoe      | d@gmail.com | ... |
+----------------------------------------------------------------+
|  3  |           3 |          2 | emlo      | e@gmail.com | ... |
+----------------------------------------------------------------+
|  4  |           1 |          2 | ches      | c@gmail.com | ... |
+----------------------------------------------------------------+

这解决了数据透视表不匹配记录的问题,因为每个客户记录都有一个唯一的键,这使得数据透视表成为正常的多对多关系。

关于mysql - 我有一个与数据库中大多数其他表相关的表。将其添加为联接是否足以使查询按预期返回?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52954219/

相关文章:

Mysql数据选择特定价格范围、产品限制和其他过滤

php - Codeigniter Session不存储数据,它只保存我们在登录表单的输入框中输入的电子邮件?

mysql - 围绕继承结构设计关系

mysql - 错误: Error 1005: Can't create table 'website.#sql-3e5_102' (errno: 150)

android - 日历提供程序如何存储无限重复事件的实例?

database - 如何在我的数据库中实现 Twitter 转发操作

PHP 脚本在 MySQL 中成功创建表但未添加数据

c# - 你如何使用 MySql 的 IN 子句

mysql - curdate() 的时间?

database - 给定与 FD 的关系,计算属性集的闭包