我想加入一张两张桌子。表中存在一列,但另一列是派生列。
event_date - exists directly in the table
deploy_date - derived using case statement
请参阅原始查询中的第6行。
1 SELECT ab.id,
2 ab.event_date,
3 CASE
4 WHEN ab.label = 'ABC' THEN ab.event_date
5 WHEN ab.label = 'DEF' THEN ab.start_date
6 END deploy_date,
7 FROM ab_bro AB
8 LEFT JOIN ab_rev rv
9 ON ab.bro_id = rv.bro_id
10 AND ab.event_date = rv.event_date
现在我想在第10行(上面)中使用deploy_date
而不是event_date
因为sql不允许在连接中使用别名,所以我尝试使用子查询
SELECT ab.id,
ab.event_date,
CASE
WHEN ab.label = 'ABC' THEN ab.event_date
WHEN ab.label = 'DEF' THEN ab.start_date
END deploy_date,
FROM ab_bro AB
LEFT JOIN ab_rev rv
ON ab.bro_id = rv.bro_id
AND
(
SELECT
CASE
WHEN AC.label = 'ABC' THEN AC.event_date
WHEN AC.label = 'DEF' THEN AC.start_date
END deploy_date from ab_bro AC) = rv.event_date
我的错误 -
错误:用作表达式的子查询返回的多行
我知道我的子查询确实返回了多行,但我不知道如何解决这个问题。
你需要做的就是在JOIN标准中使用CASE表达式:
SELECT
ab.id,
ab.event_date,
CASE
WHEN ab.label = 'ABC'
THEN ab.event_date
WHEN ab.label = 'DEF'
THEN ab.start_date
END deploy_date,
FROM ab_bro AB
LEFT JOIN ab_rev rv
ON ab.bro_id = rv.bro_id
AND rv.event_date = CASE
WHEN ab.label = 'ABC'
THEN ab.event_date
WHEN ab.label = 'DEF'
THEN ab.start_date
END
如果AND()子选择返回多于行,则可以使用限制1
SELECT ab.id,
ab.event_date,
CASE
WHEN ab.label = 'ABC' THEN ab.event_date
WHEN ab.label = 'DEF' THEN ab.start_date
END deploy_date,
FROM ab_bro AB
LEFT JOIN ab_rev rv
ON ab.bro_id = rv.bro_id
AND (
SELECT
CASE
WHEN AC.label = 'ABC' THEN AC.event_date
WHEN AC.label = 'DEF' THEN AC.start_date
END deploy_date from ab_bro AC
limit 1 ) = rv.event_date
或使用IN而不是=
SELECT ab.id,
ab.event_date,
CASE
WHEN ab.label = 'ABC' THEN ab.event_date
WHEN ab.label = 'DEF' THEN ab.start_date
END deploy_date,
FROM ab_bro AB
LEFT JOIN ab_rev rv
ON ab.bro_id = rv.bro_id
AND rv.event_date IN (
SELECT
CASE
WHEN AC.label = 'ABC' THEN AC.event_date
WHEN AC.label = 'DEF' THEN AC.start_date
END deploy_date from ab_bro AC
limit 1 )
加入内联视图而不是在CASE
子句中添加WHERE
语句至少会更加整洁一些。这样可以避免重复CASE
表达式。有些人可能会认为使用CTE而不是内联视图更清晰,更清晰:
WITH x AS (
SELECT
id,
bro_id,
event_date,
CASE label
WHEN 'ABC' THEN event_date
WHEN 'DEF' THEN start_date
END deploy_date
FROM ab_bro
)
SELECT
x.id,
x.event_date,
x.deploy_date
FROM
x
LEFT JOIN ab_rev rv
ON x.bro_id = rv.bro_id
AND x.deploy_date = rv.event_date
您可以将这两种变体视为创建一个包含派生数据的临时表作为普通列,并将其连接到另一个表。
SELECT sub.id,
sub.event_date,
sub.deploy_date
FROM (
SELECT ab.id,
ab.event_date,
ab.bro_id,
CASE
WHEN ab.label = 'ABC' THEN ab.event_date
WHEN ab.label = 'DEF' THEN ab.start_date END as deploy_date,
FROM ab_bro AB
) AS sub
LEFT JOIN ab_rev rv ON sub.bro_id = rv.bro_id
AND sub.deploy_date = rv.event_date;