到目前为止,这是我提出的在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
我尝试过的大多数加入选项都会丢失点击,没有销售,销售和没有点击等的情况,这是我发现的唯一方法,即不使用子查询就不会丢失任何案例
答案 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