【问题标题】:SQL Case column is null redefine selectorsSQL Case 列为 null 重新定义选择器
【发布时间】:2023-03-23 14:59:01
【问题描述】:

我想创建一个 SQL 选择语句,它将 JOIN 几个表和 yeidl 结果。本质上,我有两个相互独立的表。一个表包含用户(假定它具有最新和正确的信息),我有一个名为玩家的放置持有者表。占位符表有一个标记为 userID 的列,该列设置为 NULL。当用户被识别为玩家时,用户 ID 的 NULL 值将替换为用户的唯一 ID。

这让我想使用 SQL 来测试 userID 是否为 NULL。我写了以下不起作用的语句

SELECT 
    teams.*, players.number, players.position,  players.userId, 
CASE WHEN players.userId IS NULL THEN players.id ELSE userPlayer.id END AS playerId,
CASE WHEN players.userId IS NULL THEN players.firstName ELSE userPlayer.firstName END AS firstName,
CASE WHEN players.userId IS NULL THEN players.lastName ELSE userPlayer.lastName END AS lastName,
CASE WHEN players.userId IS NULL THEN players.email ELSE userPlayer.email END AS email 

FROM teams 
LEFT JOIN players ON players.teamId = teams.id 
LEFT JOIN users AS userPlayer ON userPlayer.id= players.userId 

WHERE teams.id = (:t)

这似乎非常低效。有没有更好的办法?

谢谢

【问题讨论】:

  • 您是否只想返回Player 对应的User 的结果?或者,您想返回所有名玩家,有时userId 会是NULL,有时不会?
  • 我想在玩家有对应用户时记录用户
  • 上述语句确实有效,因为它现在循环遍历团队中的球员列表
  • 有什么原因你不使用COALESCE,而不是CASE WHEN... IS NULL...
  • 我应该用 COALESCE(players.userId, userPlayer.xxxx) 替换 CASE 吗?

标签: sql join left-join


【解决方案1】:

首先,userPlayer.idplayers.userId 没有什么不同(两者都是某物,或者两者都为空),因此您可以省略该表达式。

此外,为了清晰和简洁,优先使用coalesce() 而不是case when x is null

SELECT
    teams.*, players.number, players.position, 
    players.userId AS playerId,
    COALESCE(userPlayer.firstName, players.firstName) AS firstName,
    COALESCE(userPlayer.lastName, players.lastName) AS lastName,
    COALESCE(userPlayer.email, players.email) AS email 
FROM teams 
LEFT JOIN players ON players.teamId = teams.id 
LEFT JOIN users AS userPlayer ON userPlayer.id = players.userId 
WHERE teams.id = (:t)

【讨论】:

  • 此陈述不正确“首先,userPlayer.id 与 player.userId 永远不会不同”因为 player.userId 可以为 NULL,而 userPlayer.id 将始终是唯一的字母数字值
  • @bushbrigade 但由于加入条件,如果 player.userId 为空,则不会加入用户,因此左加入将为所有用户列返回空值。因此,我的回答是正确的:对于任何给定的行,player.userId 和 users.id 具有相同的(非空)值,或者它们都是空的。
【解决方案2】:

您可以创建一个视图,您可以在其中轻松地按 id 选择团队。在这种情况下可以进行优化,因为如果 player.userId 为 null,则 user 的所有值都为 null(因为左连接)。所以你可以创建一个联合,如果你有很多空条目,这可能是有益的:

SELECT
   teams.*, players.number, players.position, players.userId AS playerId,
   players.firstName, players.lastName, players.email
FROM
   teams LEFT JOIN players ON players.teamId = teams.id
WHERE
   players.userId IS NULL OR
   NOT EXISTS(SELECT * FROM users WHERE users.id = players.userId)

UNION

SELECT
   teams.*, players.number, players.position, players.userId AS playerId,
   COALESCE(userPlayer.firstName, players.firstName) AS firstName,
   COALESCE(userPlayer.lastName, players.lastName) AS lastName,
   COALESCE(userPlayer.email, players.email) AS email
FROM
   teams
   INNER JOIN players ON players.teamId = teams.id 
   INNER JOIN users AS userPlayer ON userPlayer.id = players.userId

【讨论】:

    【解决方案3】:

    如果你的“players.userId”PK,你可以试试这个:

    SELECT 
        teams.*, players.number, players.position,  players.userId, 
    ISNULL(players.id, userPlayer.id) AS playerId,
    ISNULL(players.firstName, userPlayer.firstName) AS firstName,
    ISNULL(players.lastName, userPlayer.lastName) AS lastName,
    ISNULL(players.email, userPlayer.email) AS email 
    
    FROM teams 
    LEFT JOIN players ON players.teamId = teams.id 
    LEFT JOIN users AS userPlayer ON userPlayer.id= players.userId 
    
    WHERE teams.id = (:t)
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2014-01-04
      • 2021-02-05
      • 1970-01-01
      • 2011-07-05
      • 2021-02-16
      • 2013-07-31
      相关资源
      最近更新 更多