在join子句中使用子查询而不是列名

问题描述 投票:0回答:4

我想加入一张两张桌子。表中存在一列,但另一列是派生列。

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 

我的错误 -

错误:用作表达式的子查询返回的多行

我知道我的子查询确实返回了多行,但我不知道如何解决这个问题。

sql join subquery greenplum
4个回答
1
投票

你需要做的就是在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

0
投票

如果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 )

0
投票

加入内联视图而不是在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

您可以将这两种变体视为创建一个包含派生数据的临时表作为普通列,并将其连接到另一个表。


0
投票
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; 
© www.soinside.com 2019 - 2024. All rights reserved.