sql JOIN如果存在

时间:2014-08-08 14:23:18

标签: sql sql-server

我在下面的查询中遇到了一些问题。我的所有用户都在一个名为ItemInstances的表中,我的所有数据都包含在名为ItemPropertyValuesIntItemPropertyValuesBool的表中的用户中。

此查询正常工作,直到我添加IsBanned查询。并非所有用户都在此表中有条目,因此只返回5个用户而不是300个。我的理解是LEFT JOIN将是解决方案,但也许我误解了如何在此查询中写入此内容。

此查询的任何其他优化提示也欢迎,因为数据库是巨大的

SELECT ItemInstances.Id,
    Relics.PropertyValue AS Hugo_Relics,
    AllianceID.PropertyValue AS Hugo_AllianceID,
    Faction.PropertyValue AS Hugo_Faction,
    LevelXP.PropertyValue AS Hugo_Level,
    WeeklyRelics.PropertyValue AS Hugo_WeeklyRelics,
    UserName.PropertyValue AS Hugo_UserName,
    ItemInstances.CreatorId,
    IsBanned.PropertyValue
FROM dbo.ItemInstances
LEFT OUTER JOIN dbo.ItemPropertyValuesInt Faction
    ON Faction.RecordId = ItemInstances.Id
LEFT OUTER JOIN dbo.ItemPropertyValuesInt LevelXP
    ON LevelXP.RecordId = ItemInstances.Id
LEFT OUTER JOIN dbo.ItemPropertyValuesInt Relics
    ON ItemInstances.Id = Relics.RecordId
LEFT OUTER JOIN dbo.ItemPropertyValuesInt AllianceID
    ON ItemInstances.Id = AllianceID.RecordId
LEFT OUTER JOIN dbo.ItemPropertyValuesInt WeeklyRelics
    ON WeeklyRelics.RecordId = ItemInstances.Id
LEFT OUTER JOIN dbo.ItemPropertyValuesString UserName
    ON UserName.RecordId = ItemInstances.Id
LEFT OUTER JOIN dbo.ItemPropertyValuesBool IsBanned
    ON IsBanned.RecordId = ItemInstances.Id
WHERE Relics.PropertyId = 541
    AND AllianceID.PropertyId = 504
    AND Faction.PropertyId = 520
    AND LevelXP.PropertyId = 529
    AND WeeklyRelics.PropertyId = 730
    AND UserName.PropertyId = 554
    AND IsBanned.PropertyId = 728
ORDER BY Hugo_Relics DESC

3 个答案:

答案 0 :(得分:4)

如果在左连接表中没有匹配的记录,则需要在任何WHERE子句条件中考虑该记录。例如:

AND (IsBanned.PropertyId = 728 OR IsBanned.PropertyId IS NULL)

答案 1 :(得分:1)

即使你刚加入,你也在选择

AND IsBanned.PropertyId = 728

不在禁止表中的用户的isBanned.PropertyId为null

所以你没有选择它们。

答案 2 :(得分:1)

我对你的查询的意图并不十分清楚,但我觉得这应该是如何格式化的。

FROM dbo.ItemInstances
LEFT JOIN dbo.ItemPropertyValuesInt Faction
    ON  Faction.RecordId = ItemInstances.Id
    AND Faction.PropertyId = 520
LEFT JOIN dbo.ItemPropertyValuesInt LevelXP
    ON  LevelXP.RecordId = ItemInstances.Id
    AND LevelXP.PropertyId = 529
LEFT JOIN dbo.ItemPropertyValuesInt Relics
    ON  Relics.RecordId = ItemInstances.Id
    AND Relics.PropertyId = 541
LEFT JOIN dbo.ItemPropertyValuesInt AllianceID
    ON  AllianceID.RecordId = ItemInstances.Id
    AND AllianceID.PropertyId = 504
LEFT JOIN dbo.ItemPropertyValuesInt WeeklyRelics
    ON  WeeklyRelics.RecordId = ItemInstances.Id
    AND WeeklyRelics.PropertyId = 730
LEFT JOIN dbo.ItemPropertyValuesString UserName
    ON  UserName.RecordId = ItemInstances.Id
    AND UserName.PropertyId = 554
LEFT JOIN dbo.ItemPropertyValuesBool IsBanned
    ON  IsBanned.RecordId = ItemInstances.Id
    AND IsBanned.PropertyId = 728
WHERE ItemInstances.Id = ?

Gordon Linoff的评论很好地解释了这一点。

LEFT JOIN b ON b.id = a.id AND b.value = x
--All records from [a] retained
--Only records from [b] where b.value = x LEFT JOIN'd to [a]

非常不同
LEFT JOIN b ON b.id = a.id WHERE b.value = x
--Only records from [a] and [b] where [b].value = x are retained