簡體   English   中英

where子句中的子查詢(mysql)

[英]subquery in where clause (mysql)

SELECT d.userID, (d.amountSuccessfulDeposits), (d.numberSuccessfulDeposits), cl.notes, d.asofdate, cl.send_date
FROM campaign_list cl
INNER JOIN deposit d
    on d.userid = cl.userid
WHERE cl.send_date > date(CURDATE()) - INTERVAL 7 DAY
    AND cl.send_date < date(CURDATE()) - INTERVAL 1 DAY
    AND d.asofdate > date(CURDATE()) - INTERVAL 7 DAY
    AND d.asofdate < date(CURDATE()) - INTERVAL 1 DAY
    and cl.notes in ('report11', 'report12', 'report13', 'report14', 'report15') 
    and d.asofdate > cl.send_date

用戶ID輸入廣告系列后(報告11-15),查詢會計算存款數量。 “send_date”是用戶ID輸入廣告系列的日期。 但是,如果用戶ID進一步推進到另一組廣告系列(報告16-20),則在進入第二組廣告系列(16-20)后進行的存款不應計入第一組廣告系列(11 - 15)查詢總計。

例:

Bob在1/20上輸入報告11

鮑勃在1/21存款100美元

鮑勃在1/24輸入報告16

鮑勃在1/25存款500美元

因此,上述查詢只應為Bob返回100美元。

userID;  amountSuccessfulDeposits; numberSuccessfulDeposits; notes;    asofdate;     send_date
2575192;   100.00;                       1;                 report11    ;2016-01-21    ; 2016-01-20

以下查詢無效

SELECT d.userID, (d.amountSuccessfulDeposits), (d.numberSuccessfulDeposits), cl.notes, d.asofdate, cl.send_date
FROM campaign_list cl
INNER JOIN deposit d
    on d.userid = cl.userid
WHERE cl.send_date > date(CURDATE()) - INTERVAL 7 DAY
    AND cl.send_date < date(CURDATE()) - INTERVAL 1 DAY
    AND d.asofdate > date(CURDATE()) - INTERVAL 7 DAY
    AND d.asofdate < date(CURDATE()) - INTERVAL 1 DAY
    and cl.notes in ('report11', 'report12', 'report13', 'report14', 'report15') 
    and d.asofdate > cl.send_date 
    AND (   
                (SELECT (ocl.send_date) 
                    FROM campaign_list ocl
                    WHERE ocl.userID = cl.userID
                        and ocl.notes in ('report16', 'report17', 'report18', 'report19', 'report20')                   
                ) > d.asofdate
        )

我會使用內聯視圖來獲取后續廣告系列的“最早”的send_date。 (目前尚不清楚特定廣告系列之間是否存在任何關系。如果Bob進入任何廣告系列16-20,那么該廣告系列的send_date將是以前所有廣告系列的“截止”11-15)

如果沒有完全理解規范,我有點不願意建議一個“適用於你”的查詢。

但基於給定的查詢,我會做這樣的事情:

SELECT d.userid
     , d.amountSuccessfulDeposits
     , d.numberSuccessfulDeposits
     , cl.notes
     , d.asofdate
     , cl.send_date
  FROM campaign_list cl

/ *在這里,我將為每個用戶ID創建一個內聯視圖,該視圖從后續廣告系列16-20中獲取“最早的” send_date 我做了一個外部聯接到這個集合,像這樣* /

  LEFT
  JOIN ( -- inline view to get earliest send_date
         SELECT ocl.userid
              , MIN(ocl.send_date) AS min_send_date
           FROM campaign_list ocl
          WHERE ocl.notes IN ('report16'
                             ,'report17'
                             ,'report18'
                             ,'report19'
                             ,'report20'
                             )
          GROUP BY ocl.userid
       ) oc
    ON oc.userid = cl.userid

/ *有了這個,我們將從sent_date的后續廣告系列中獲得“最早的” sent_date 現在,這與cl廣告系列中的行相關聯。 現在,我們可以加入deposit表。 我的偏好是將d列的所有條件放入連接的ON子句,而不是WHERE子句* /

  JOIN deposit d
    ON d.userid     = cl.userid
   AND d.asofdate   > cl.send_date
   AND d.asofdate   > DATE(NOW()) + INTERVAL -7 DAY
   AND d.asofdate   < DATE(NOW()) + INTERVAL -1 DAY

/ *現在這里的訣竅...... * /

   AND d.asofdate  <= IFNULL(oc.min_send_date,d.asofdate + INTERVAL 1 DAY)

包括限制來自后續廣告系列中最早的send_date之后或之后具有asofdate deposit d行的條件。 棘手的部分是我們需要OR條件,當沒有跟隨競選活動時,最早的send_date將為NULL。 如果oc.min_send_date的值不是NULL,那么我們只使用它。 如果它是NULL,我們替換一個不會限制從d返回行的值。 大於d.asofdate的值將起作用。

我正在使用<= (小於或等於)測試。 如果我們只是用一個<測試,這似乎是一個depositasofdate是在一天send_date將是一個無人區......它不會為先前的活動返回,因為我們已經有了一個> (大於)限制d.asofdate > cl.send_date

那么WHERE子句對cl * /中的行有限制

 WHERE cl.send_date > DATE(NOW()) + INTERVAL -7 DAY
   AND cl.send_date < DATE(NOW()) + INTERVAL -1 DAY
   AND cl.notes    IN ('report11'
                      ,'report12'
                      ,'report13'
                      ,'report14'
                      ,'report15'
                      )

這就是我要采取的方法。


或者,在相關條款中的相關子信息

如果有一些原因你需要WHERE子句中包含一個從屬子查詢...你可以把它寫成一個EXISTS謂詞...檢查是否有任何跟隨廣告的發送方式早於asofdate,例如

  AND NOT EXISTS ( SELECT 1
                     FROM campaign_list ocl
                    WHERE ocl.userID    = cl.userid
                      AND ocl.send_date < d.asofdate
                      AND ocl.notes    IN ('report16'
                                          ,'report17'
                                          ,'report18'
                                          ,'report19'
                                          ,'report20'
                                          )
                 )

或者,如果有某些原因需要對查詢的返回進行標量比較(執行小於/大於比較),則子查詢的返回必須是標量...查詢必須返回單個列並返回(最多)一行。

要確保返回的行不超過一行,可以使用聚合(例如MIN() ,或者可以使用LIMIT子句。並且您需要准備好處理如果沒有找到行將返回的NULL值。

 AND ( d.asofdate <= IFNULL( ( SELECT ocl.send_date 
                                 FROM campaign_list ocl
                                WHERE ocl.userID     = cl.userid
                                  AND ocl.send_date >= d.asofdate
                                  AND ocl.notes     IN ('report16'
                                                       ,'report17'
                                                       ,'report18'
                                                       ,'report19'
                                                       ,'report20'
                                                       )
                                ORDER BY ocl.send_date ASC
                                LIMIT 1
                             )
                     , d.asofdate
                     )

MySQL中可能存在一些限制, WHERE子句中可能不允許使用依賴子查詢。 你肯定可以在HAVING子句中得到它。 但是,在GROUP BY操作之后,HAVING子句幾乎在語句執行中被評估。

暫無
暫無

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

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