簡體   English   中英

在連接子句中使用子查詢代替列名

[英]Using subquery in join clause instead of column name

我正在嘗試加入兩張桌子。 表中存在一列,但另一列是派生的。

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()子查詢更多地重調了行數,則可以使用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 )

加入內聯視圖,而不是在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

您可以將這兩種變體都視為創建一個臨時表,該表包含派生數據作為普通列,並將其連接到另一個表。

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; 

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM