上下文是这样的:一台机器在某个位置或位置内的某个位置。这里有两种情况,一台机器可以在positionId中有一个值,或者,如果位置仅容纳一台机器,那么在positionId中它的值为0。 我编写了一个查询以返回序列号,名称,地址,说明和标识符的值,并考虑到存在或不存在位置的情况:
SELECT machine.`serialNumber`, location.`name`, location.`address`, product.`identifier`,
(CASE WHEN EXISTS(SELECT `description`
FROM `positions` AS pos
WHERE pos.`locationId` = `machine`.`id`)
THEN `description`
ELSE 0
END) AS existPos
FROM machine
INNER JOIN location
ON machine.`locationId` = location.`id`
INNER JOIN positions
INNER JOIN product
ON machine.`id` = product.`machineId`
WHERE machine.`id` = 5
结果是同一数据的多行。我在哪里做错了?
答案 0 :(得分:0)
您可以尝试以下方法吗?
SELECT
machine.`serialNumber`,
location.`name`,
location.`address`,
product.`identifier`,
(CASE WHEN positions.Id is not null
THEN `description`
ELSE 0
END) AS existPos
FROM
machine
INNER JOIN
location
ON machine.`locationId` = location.`id`
LEFT JOIN
positions
on positions.`Id` = machine.`positionId`
INNER JOIN
product
ON machine.`id` = product.`machineId`
WHERE machine.`id` = 5
答案 1 :(得分:0)
我猜您正在使用MySQL。正如its documentation所说,
在MySQL中,JOIN,CROSS JOIN和INNER JOIN是语法等效项(它们可以相互替换)。在标准SQL中,它们不是等效的。 INNER JOIN与ON子句一起使用,否则使用CROSS JOIN。
这意味着您的INNER JOIN positions
实际上是CROSS JOIN,因为没有ON子句。这就是为什么您会得到重复的行。如果您还从positions
表中选择某些列,则会看到其中的区别。
此外,由于a machine is in a location or in a position inside a location
,您不应该对location
和positions
使用INNER JOIN。在您的代码中,location
被内部联接后,没有locationId
-FK的机器全部丢失。如果这不是您期望的,那么两个表都应由LEFT JOIN联接。
LEFT JOIN location
ON machine.`locationId` = location.`id`
LEFT JOIN positions
ON machine.`positionId` = positions.`id`
对我来说,另外一件奇怪的事情是WHERE pos.locationId = machine.id
。您在上面提供的图中未描述此关系。我猜想您可能希望将其更改为WHERE pos.id = machine.positionId
。