有没有办法在同一列上进行SELF JOIN?

时间:2015-01-20 22:41:07

标签: mysql sql inner-join one-to-many foreign-key-relationship

我目前有一个不优雅的解决方案,需要一次迭代数千行,我想知道是否可以使用单个SQL语句执行此操作。

我有一个名为history的数据库表,其中包含另一个名为inventory的数据库上的所有事务的记录。两个数据库共享一个名为pKey的列(外键)。

我的库存数据库:

| ID | pKey | model | room | ip | active | ... |

我的历史数据库: pKey是外键

| ID | pKey | fieldName | oldValue | newValue |

在历史数据库中,单个pKey可以有超过20个事务。我想找到历史中包含的所有行:

  1. A的fieldName和B的oldValue
  2. C的fieldName和D的oldValue
  3. 相同的pKey。
  4. 即。假设我们发现历史表中有一行,其fieldName为A,旧值为B,只有在搜索fieldName为C和oldValue的行时,与该行关联的pKey才会生效。 D。

    在做了一些研究之后,似乎SELF JOIN是一个不错的选择,但是因为我试图在同一列上进行SELF JOIN而遇到错误。以下是我的发言:

    SELECT pKey FROM `history` INNER JOIN history ON history.pKey=history.pKey WHERE `fieldName` = 'ipAddress' AND `oldValue` LIKE '129.97%'
    

    编辑:我在这里写下自己的陈述是错误的;我只想选择pKey结果。

3 个答案:

答案 0 :(得分:2)

当您需要执行SELF-JOIN时,您必须为要加入的表的副本提供别名。

请查看下面的查询 - 这里双方都有别名:

SELECT 
    history_AB.pKey
FROM 
    history  AS  history_AB
    INNER JOIN history  AS  history_CD 
        ON history_AB.pKey = history_CD.pKey 
WHERE 
    (history_AB.fieldName = 'A' AND history_AB.oldValue LIKE 'B%')
    AND (history_CD.fieldName = 'C' AND history_CD.oldValue LIKE 'D%')

WHERE条款中,您在问题中提到了条件:

  

(...)说我们发现历史表中有一行   fieldName of A和old Value of B,结果只有在有效时才有效   与该行关联的pKey也会在搜索行时出现   fieldName为C,oldValue为D

我希望我能很好地理解这个问题,它可能对你有所帮助。

答案 1 :(得分:2)

您必须将历史的两个实例标识为单独的元素。使用你的" ABCD"示例而不是您的陈述:

SELECT * FROM history h1 
INNER JOIN history h2
ON h1.pKey=h2.pKey 
WHERE h1.fieldName = 'A' AND h1.oldValue = 'B' 
AND h2.fieldName = 'C' AND h2.oldValue = 'D'

答案 2 :(得分:1)

如果进行自联接,则通常需要分配表别名,以便能够明确地引用任一表的任何列。因此,你可能想要这样的东西:

SELECT
  histA.pKey AS pKey,
  histA.newValue AS newA,
  histC.newValue AS newC,
FROM
  history histA
  INNER JOIN history histC
    ON histA.pKey = histC.pKey
WHERE
  histA.fieldName = 'A'
  AND histA.oldValue = 'B'
  AND histC.fieldName = 'C'
  AND histC.oldValue = 'D'

当然,您可以根据需要编写选择列表,包括只选择*,但我建议至少指定列别名以帮助您理清哪些数据来自哪个表。