在连接子句中使用子查询代替列名

时间:2019-04-24 19:08:23

标签: sql join subquery greenplum

我正试图加入两个表。表中存在一列,但另一列是派生的。

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 

我的错误-

  

错误:用作查询的子查询返回的一行以上

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

4 个答案:

答案 0 :(得分: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

答案 1 :(得分:0)

如果AND()子选择重调更多行,则可以使用limit1

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 )

答案 2 :(得分: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

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

答案 3 :(得分: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;