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

时间:2018-10-23 16:55:05

标签: 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 | ... |
+-----------------------------------------------------------------------------+

(枢轴)customer_profile:

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

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

customer和profile表均具有组合键(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键加入 这是我们目前正在使用的方式,我无法确定它是否适用于所有情况,但尚未引起任何意外的结果。

问题

我的主要问题是我不知道该怎么处理company表。 将我的公司表加入到客户表中是否足以删除所有不希望的记录,而不是我目前拥有的东西?

像这样吗?

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而不是按名字进行搜索,并将'更改为` 这就是应该的悲痛。

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

修改

查询背后的逻辑是

当该公司的此客户(c.id和c.company_id)拥有与该公司的个人资料时,将获得名称和个人资料详细信息。

1 个答案:

答案 0 :(得分:0)

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

在客户表上这样:

+-----+-------------+------------------------+-------------+-----+
| 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 | ... |
+----------------------------------------------------------------+

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