SQL 案例列为空重新定义选择器
SQL Case column is null redefine selectors
我想创建一个 SQL select 语句,它将连接一些 tables 和 yeidl 结果。本质上,我有两个相互独立的 table。一个 table 包含用户(假设拥有最新和正确的信息),我有一个名为 players 的持有人 table。占位符 table 有一个标记为 userID 的列,该列设置为 NULL。当用户被识别为玩家时,userID 的 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)
这看起来效率很低。有没有更好的方法?
谢谢
首先,userPlayer.id
与 players.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)
您可以创建一个视图,您可以在其中轻松地 select 按 ID 显示团队。在这种情况下,可以进行优化,因为如果 players.userId 为空,则 user 的所有值都为空(因为左连接)。所以你可以创建一个联合,如果你有很多空条目,它可能是有益的:
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
如果你"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)
我想创建一个 SQL select 语句,它将连接一些 tables 和 yeidl 结果。本质上,我有两个相互独立的 table。一个 table 包含用户(假设拥有最新和正确的信息),我有一个名为 players 的持有人 table。占位符 table 有一个标记为 userID 的列,该列设置为 NULL。当用户被识别为玩家时,userID 的 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)
这看起来效率很低。有没有更好的方法?
谢谢
首先,userPlayer.id
与 players.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)
您可以创建一个视图,您可以在其中轻松地 select 按 ID 显示团队。在这种情况下,可以进行优化,因为如果 players.userId 为空,则 user 的所有值都为空(因为左连接)。所以你可以创建一个联合,如果你有很多空条目,它可能是有益的:
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
如果你"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)