可以使用 CASE 选择要 JOIN 的表吗?

bau*_*dot 6 postgresql join case

我正在尝试使用 CASE 表达式来选择每行应与哪个表连接。

假设我的游戏中有一个 item_instances 表,其中包含游戏世界中的所有项目,其中一些项目是 item_templates 表中通用项目的千篇一律的副本,而其他项目则以模板开始,然后当玩家使用它们时获得独特的属性。它们现在存储在 unique_items 表中。

因此,当我在 item_instances 表中找到某个项目的记录时,我想查找有关它的更多信息,并且需要从正确的表中提取该信息。

这是我一直在尝试但没有成功的事情:

SELECT item_table, item_id, *
FROM item_instances AS ii
JOIN
CASE ii.item_table
    WHEN 0 THEN 'item_templates'
    WHEN 1 THEN 'unique_items'
    ELSE 'unique_items'
END
ON CASE = ii.item_id;
Run Code Online (Sandbox Code Playgroud)

如果有语法的快速修复,我很想听听。或者,如果这是您在概念上无法做到的事情 - 让每一行选择自己的连接 - 我很乐意获得更深入解释的链接。

过去,我通过执行两个 SELECT 来完成类似的操作,其中一个针对 item_templates 表,另一个针对 unique_items 表,并采用它们的 UNION。这感觉是一种更正确且更少浪费的方法。如果不是出于某种原因与 SQL 更深层次的架构有关,我想了解为什么。

小智 9

CASE 表达式返回单个值。它不能返回标识符(例如表引用)。并且它的值不能用来代替表名

处理这种可选依赖关系的典型方法是连接到每个表并在连接条件中包含选择表的条件。为了取回行,您将需要一个外连接,因为您不知道哪个表中会有匹配项

SELECT item_table, item_id, *
FROM item_instances AS ii
  LEFT JOIN item_templates it ON ii.item_id = it.item_id and ii.item_table = 0
  LEFT JOIN unique_items ui ON ii.item_id = ui.item_id and ii.item_table = 1
Run Code Online (Sandbox Code Playgroud)

然后,您可以在 SELECT 列表中使用coalesce(),从任一表中获取非空值。

  • 因为像“42”或“foobar”这样的值就是:一个**值**。表名是一个标识符。在 SQL 中,标识符和值是两个截然不同的东西 (2认同)