试图看看是否有更好的方法来使用连接来构造此查询

时间:2018-02-21 17:59:05

标签: mysql sql

到目前为止,这是我提出的在mySQL中进行此查询的最佳方法,但我只是想确保使用连接没有更有效的方法来执行此操作,或者如果这或多或少不是gunna kill性能与

SELECT r.CAMPAIGN_ID as ID, ref.VALUE as VALUE, SUM(CLICKS_IN) as cin, SUM(CLICKS_OUT) as cout, SUM(SALES) as sin 
FROM (
    SELECT CAMPAIGN_ID, COUNT(DISTINCT BIN_IP) AS CLICKS_IN, 0 AS CLICKS_OUT, 0 AS SALES FROM CLICKS_IN WHERE LANDER = ? AND TIME BETWEEN ? AND ? GROUP BY CAMPAIGN_ID
    UNION
    SELECT CAMPAIGN_ID, 0 AS CLICKS_IN, COUNT(DISTINCT BIN_IP) AS CLICKS_OUT, 0 AS SALES FROM CLICKS_OUT WHERE LANDER = ? AND TIME BETWEEN ? AND ? GROUP BY CAMPAIGN_ID
    UNION
    SELECT CAMPAIGN_ID, 0 AS CLICKS_IN, 0 AS CLICKS_OUT, SUM(REVENUE) AS SALES FROM CONVERSIONS WHERE LANDER = ? AND TIME BETWEEN ? AND ? GROUP BY CAMPAIGN_ID ) as r
INNER JOIN
    CLICKS_CAMPAIGN as ref ON ref.ID = r.CAMPAIGN_ID
GROUP BY ID, VALUE

我尝试过的大多数加入选项都会丢失点击,没有销售,销售和没有点击等的情况,这是我发现的唯一方法,即不使用子查询就不会丢失任何案例

1 个答案:

答案 0 :(得分:0)

当您需要同时从多个一对多关系中获取聚合值时,每个聚合都需要在子查询中执行(或者可以像在原始查询中一样在UNION中完成;正如Barmar指出的那样,查询实际上是检索此类数据的查询的一种相当常见的形式)

SELECT cc.ID, cc.VALUE, cIn.CLICKS_IN, cOut.CLICKS_OUT, cSales.SALES
FROM CLICKS_CAMPAIGN AS cc 
LEFT JOIN (SELECT CAMPAIGN_ID, COUNT(DISTINCT BIN_IP) AS CLICKS_IN 
           FROM CLICKS_IN 
           WHERE LANDER = ? AND TIME BETWEEN ? AND ? 
           GROUP BY CAMPAIGN_ID
          ) AS cIn ON cIn.CAMPAIGN_ID = cc.ID
LEFT JOIN (SELECT CAMPAIGN_ID, COUNT(DISTINCT BIN_IP) AS CLICKS_OUT
           FROM CLICKS_OUT 
           WHERE LANDER = ? AND TIME BETWEEN ? AND ? 
           GROUP BY CAMPAIGN_ID
          ) AS cOut ON cOut.CAMPAIGN_ID = cc.ID
LEFT JOIN (SELECT CAMPAIGN_ID, SUM(REVENUE) AS SALES 
           FROM CONVERSIONS 
           WHERE LANDER = ? AND TIME BETWEEN ? AND ? 
           GROUP BY CAMPAIGN_ID
          ) AS cSales ON cSales.CAMPAIGN_ID = cc.ID
GROUP BY cc.ID, cc.VALUE
;

这与原始查询不完全相同,因为您将获得所有“广告系列”,即使没有“点击”或销售的广告系列也是如此;但如果这很重要;你可以添加一个WHERE或HAVING cIn.CLICKS_IN IS NOT NULL OR cOut.CLICKS_OUT IS NOT NULL OR cSales.SALES IS NOT NULL