2016-10-17 141 views
1
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 

在用戶標識輸入活動(報告11-15)之後,查詢計算存入的數量。 「send_date」是userID輸入到活動中的日期。但是,如果用戶ID進一步進展到另一組活動(報告16-20),則在進入第二組活動(16-20)後進行的存款不應計入第一組活動(11-15)查詢總計。where子句中的子查詢(mysql)

實施例:

鮑勃進入上1/21

鮑勃1/20

鮑勃存款$ 100報告11進入上1/24

鮑勃16報告存款$ 1/12

因此,上述查詢應該只會爲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 
     ) 
+0

我們可以通過一些示例選項卡數據和期望的輸出?最快的方法來在這裏獲得高質量的答案。 –

+0

你如何在表格中輸入數字?當我從mysql客戶端複製並粘貼時,這是一團糟 – eddd83

+0

在每行的前面添加四個空格,這將強制等寬字體文本。因此,只需在記事本中創建一個漂亮的表格,在每行的開頭添加四個空格,然後將其轉儲到您的問題中。 –

回答

0

我會用內嵌視圖,以便得到有關活動後續的「最早」 SEND_DATE。 (目前還不清楚特定廣告系列之間是否存在任何關係,如果Bob進入任何廣告系列16-20,則該廣告系列的發送日期是之前所有廣告系列的「中斷」)11)

沒有滿對規範的理解,我有點不情願地建議一個能夠「爲你工作」的查詢。

但根據給定的查詢,我會做這樣的事情:

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

/*在這裏,我將創建一個獲取從遵循「最早的」 send_date征戰內嵌視圖16 20,針對每個用戶。我做了一個外連接到該集合,像這樣*/

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。這現在與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) 

包括從deposit d該日或之後從活動的後續最早send_dateasofdate限制行的條件。棘手的部分是我們需要一個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子句

如果有某種原因,你需要包括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條款是肯定的。但是,HAVING子句得到的幾乎是最後的評估在GROUP BY操作之後執行語句。