2016-10-17 142 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操作之后执行语句。