Попытка выяснить, есть ли лучший способ структурировать этот запрос с помощью объединений

0

Пока это самый лучший способ, с помощью которого я делаю этот запрос в 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
    Я имею в виду, что мне просто хочется привести 2 \ 3 полей к 0 в других запросах, тогда выполнение операции суммирования не может быть самым элегантным решением.
Показать ещё 2 комментария
Теги:

1 ответ

0
Лучший ответ

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

Ещё вопросы

Сообщество Overcoder
Наверх
Меню