【发布时间】:2018-03-11 02:50:48
【问题描述】:
我正在尝试加入 MySQL 中的一些表。我们的设置有点独特,所以我尽量解释清楚。
- 我有一个表'INVENTORY',它代表当前的库存项目。
- 这些项目存储在表“COMPONENT”中
- 组件正在安装中使用。
- 每个用户都可以进行多次安装,并且同一个组件也可以在多次安装中使用。
- 要将组件唯一映射到安装,可以将其分配给产品。产品与安装具有 1-1 关系。组件与安装没有直接关系
- 要最终将产品分配给特定安装,使用映射表 COMPOMENT_PRODUCT。
示例:
一个组件就像一个零件,比方说一个螺丝。该螺钉用于计算机。同一个螺丝可以用在多台电脑上。但是每台计算机只能用于一个特定的安装。
TABLE COMPOMENT_PRODUCT
COMPOMENT_ID PRODUCT_ID
1 1
1 2
2 1
2 2
所以我们有两个安装相关的组件 C1 和 C2。
TABLE INVENTORY
COMPOMENT_ID INSTALLATION_ID ON_STOCK
1 1 5
1 2 2
我想要达到的目标 现在,我想检索所有组件的库存状态。但是,并非每个组件都有库存记录。在这些情况下,库存中的 ON_STOCK 值应为 NULL
这意味着,对于这个例子,我希望得到以下结果
COMPOMENT_ID PRODUCT_ID ON_STOCK
1 1 5
1 2 2
2 1 NULL
2 2 NULL
但是执行这个查询:
SELECT DISTINCT
COMPONENT_PRODUCT.COMPONENT_ID,
COMPONENT_PRODUCT.PRODUCT_ID,
INVENTORY.ON_STOCK
FROM INVENTORY
RIGHT JOIN COMPONENT_PRODUCT ON COMPONENT_PRODUCT.COMPONENT_ID =
INVENTORY.COMPONENT_ID
返回以下结果集:
COMPONENT_ID PRODUCT_ID ON_STOCK
1 1 5
1 2 5
1 1 2
1 2 2
2 1 (null)
2 2 (null)
现在,我的下一个想法是,“当然,这就是连接的行为方式,好吧,我需要对结果进行分组”。但是 SQL 的工作方式,聚合并不是完全可预测的。所以当我
GROUP BY COMPONENT_PRODUCT.COMPONENT_ID,COMPONENT_PRODUCT.PRODUCT_ID
我得到这个结果:
COMPONENT_ID PRODUCT_ID ON_STOCK
1 1 5
1 2 5
2 1 (null)
2 2 (null)
我这里准备了一个 Fiddle:http://sqlfiddle.com/#!9/71ca87
我在这里忘记了什么?在此先感谢您的任何指点。
【问题讨论】:
-
那么物品和组件是一回事吗?产品和安装也一样?
-
是和不是。项目和组件相同,安装和产品不同。组件基本上是在安装中使用的部件。由于同一个组件可以在多个安装中使用,我们需要一种方法来确定在哪些安装上使用这些组件。这是通过产品完成的。一个产品只能在一次安装中使用,并且一个组件是该产品的一部分。
-
"组件 C1 和 C2 用于安装 I1、I2。"并且表“INVENTORY”与“组件与安装没有直接关系”相矛盾。因此,已经不清楚组件“1”如何具有 2 个不同的 on_stock 值。假设你的模型是正确的,你的问题是你的加入(它已经列出了错误的股票价值,如果你分组它们不会消失)。但是由于您已经有一个包含所有允许组合的表,您似乎只需使用表
COMPOMENT_PRODUCT并将其与库存表(通过 1:1 产品安装关系)连接起来。 -
GROUP BY的目的是计算聚合值(使用 aggregate (GROUP BY) functions,而不是删除重复项。它甚至不从表中返回行,它生成 它返回的行。而且,顺便说一句,聚合是完全可预测的。当一个人不使用聚合函数并期望引擎读取他们的想法并从一组值中选择某个值时,它不会按预期工作。您的GROUP BY查询无效,这就是其结果不可预测的原因。 -
您在
JOIN查询中获得了额外的行,因为它不包含产品和安装之间的链接。将此链接放入查询(它可能是另一个表)和相应的ON条件中,您将获得所需的结果,而无需使用DISTINCT(无论如何,它在这里没有帮助)。
标签: mysql join duplicates