具有内部联接条件的SQL查询

时间:2018-07-11 10:32:54

标签: sql phpmyadmin

enter image description here

上下文是这样的:一台机器在某个位置或位置内的某个位置。这里有两种情况,一台机器可以在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

结果是同一数据的多行。我在哪里做错了?

2 个答案:

答案 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,您不应该对locationpositions使用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