where子句中的子查询(mysql)

时间:2016-10-17 22:27:19

标签: mysql subquery where

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),查询会计算存款数量。 &#34; SEND_DATE&#34;是用户ID输入广告系列的日期。但是,如果用户ID进一步推进到另一组广告系列(报告16-20),则在进入第二组广告系列(16-20)后进行的存款不应计入第一组广告系列(11 - 15)查询总。

示例:

鲍勃在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
        )

1 个答案:

答案 0 :(得分:0)

我会使用内联视图来获得最早的&#34; send_date用于后续广告系列。 (目前尚不清楚特定广告系列之间是否存在任何关系。如果Bob进入任何广告系列16-20,则该广告系列的send_date为&#34;切断&#34;对于所有以前的广告系列11- 15)

如果没有完全理解规范,我有点不愿意建议一个能够&#34;工作&#34;对你而言。

但根据给定的查询,我会做这样的事情:

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

/ *在这里,我会创建一个内联视图,以获得最早的&#34;对于每个用户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

/ *有了这个,我们将拥有最早的&#34;来自后续广告系列的sent_date。现在,这与cl广告系列中的行相关联。现在,我们可以加入deposit表。我的偏好是将{em>所有条件放在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的{​​{1}}行。棘手的部分是我们需要OR条件,当没有跟随竞选活动时,最早的asofdate将为NULL。如果send_date的值不是NULL,那么我们就这样使用它。如果它为NULL,我们替换一个不会限制从send_date返回行的值。大于oc.min_send_date的值将起作用。

我正在使用d(小于或等于)测试。如果我们只是使用d.asofdate测试,那么<= <deposit似乎在相同的日期,asofdate将是没有人的土地......因为我们已经有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谓词。 。检查是否有任何关于send_date的跟随广告系列早于asofdate,例如

EXISTS

或者,如果有某些原因你需要对查询的返回进行标量比较(做小于/大于比较),那么子查询的返回必须是标量...查询必须返回单个列并返回(最多)一行。

要确保返回的行不超过一行,您可以使用聚合(例如 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()子句。并且您需要准备好处理NULL值如果没有找到行,将会返回。

LIMIT

MySQL中可能存在一些限制, 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 ) 子句中可能不允许使用相关子查询。你可以在WHERE条款中得到它。但是,在GROUP BY操作之后,HAVING子句几乎在语句执行中被评估。