Пока это самый лучший способ, с помощью которого я делаю этот запрос в 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
Большинство вариантов соединения, которые я пытался потерять, там, где есть клики, а также нет продаж, продаж и кликов и т.д., И это единственный способ, который я понял, который не теряет никаких случаев без использования подзапросов.
Когда вам нужны совокупные значения из нескольких отношений "один ко многим" сразу, каждая агрегация должна выполняться в подзапросе (или это может быть сделано в UNION, как ваш исходный запрос, как отметил Бармар, ваш запрос на самом деле довольно распространен форма запроса для получения такого рода данных)
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