在连接子句中使用子查询而不是列名
Using subquery in join clause instead of column name
我正在尝试加入两个table。 table 中存在一列,但另一列是派生的。
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
我的错误-
ERROR: more than one row returned by a subquery used as an expression
我知道我的子查询确实返回了不止一行,但我不知道如何解决这个问题。
您在这里需要做的就是在 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 )
加入内联视图而不是在 WHERE
子句中放置 CASE
语句至少会更整洁一些。这将使您避免重复 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
您可以将这两种变体视为创建一个临时 table 包含作为普通列的派生数据,并将其连接到另一个 table。
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;
我正在尝试加入两个table。 table 中存在一列,但另一列是派生的。
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
我的错误-
ERROR: more than one row returned by a subquery used as an expression
我知道我的子查询确实返回了不止一行,但我不知道如何解决这个问题。
您在这里需要做的就是在 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 )
加入内联视图而不是在 WHERE
子句中放置 CASE
语句至少会更整洁一些。这将使您避免重复 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
您可以将这两种变体视为创建一个临时 table 包含作为普通列的派生数据,并将其连接到另一个 table。
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;