MYSQL sum () для отдельных строк - PullRequest
39 голосов
/ 13 марта 2010

Я ищу помощь с использованием sum () в моем запросе SQL:

SELECT links.id, 
       count(DISTINCT stats.id) as clicks, 
       count(DISTINCT conversions.id) as conversions, 
       sum(conversions.value) as conversion_value 
FROM links 
LEFT OUTER JOIN stats ON links.id = stats.parent_id 
LEFT OUTER JOIN conversions ON links.id = conversions.link_id 
GROUP BY links.id 
ORDER BY links.created desc;

Я использую DISTINCT, потому что я делаю "group by", и это гарантирует, что одна и та же строка не будет подсчитана более одного раза.

Проблема в том, что SUM (conversions.value) подсчитывает «значение» для каждой строки более одного раза (из-за группировки по)

Я в основном хочу сделать SUM(conversions.value) для каждого DISTINCT Conversions.id.

Это возможно?

Ответы [ 7 ]

70 голосов
/ 14 марта 2010

Я могу ошибаться, но из того, что я понимаю

  • conversions.id - это первичный ключ вашей таблицы преобразований
  • stats.id - это первичный ключ вашей таблицы stats

Таким образом, для каждого Conversions.id у вас есть не более одного links.id.

Ваш запрос немного напоминает декартово произведение из 2 комплектов:

[clicks]
SELECT *
FROM links 
LEFT OUTER JOIN stats ON links.id = stats.parent_id 

[conversions]
SELECT *
FROM links 
LEFT OUTER JOIN conversions ON links.id = conversions.link_id 

и для каждой ссылки вы получаете sizeof ([клики]) x sizeof ([конверсии]) строк

Как вы отметили, количество уникальных конверсий в вашем запросе можно получить через

count(distinct conversions.id) = sizeof([conversions])

это отличное удаляет все строки [щелчков] в декартовом произведении

но ясно

sum(conversions.value) = sum([conversions].value) * sizeof([clicks])

В вашем случае, начиная с

count(*) = sizeof([clicks]) x sizeof([conversions])
count(*) = sizeof([clicks]) x count(distinct conversions.id)

у вас есть

sizeof([clicks]) = count(*)/count(distinct conversions.id)

поэтому я бы протестировал ваш запрос с помощью

SELECT links.id, 
   count(DISTINCT stats.id) as clicks, 
   count(DISTINCT conversions.id) as conversions, 
   sum(conversions.value)*count(DISTINCT conversions.id)/count(*) as conversion_value 
FROM links 
LEFT OUTER JOIN stats ON links.id = stats.parent_id 
LEFT OUTER JOIN conversions ON links.id = conversions.link_id 
GROUP BY links.id 
ORDER BY links.created desc;

Держите меня в курсе! Джером

10 голосов
/ 08 августа 2013

Решение Джерома на самом деле неверно и может дать неправильные результаты !!

sum(conversions.value)*count(DISTINCT conversions.id)/count(*) as conversion_value

давайте предположим, что следующая таблица

conversions
id value
1 5
1 5
1 5
2 2
3 1

правильная сумма значений для разных идентификаторов будет 8. Формула Джерома производит:

sum(conversions.value) = 18
count(distinct conversions.id) = 3
count(*) = 5
18*3/5 = 9.6 != 8
7 голосов
/ 20 марта 2010

Для объяснения того, почему вы видели неправильные числа, прочитайте это .

Я думаю, что Джером знает, что является причиной вашей ошибки. Запрос Брайсона будет работать, хотя наличие этого подзапроса в SELECT может быть неэффективным.

4 голосов
/ 19 марта 2010

Используйте следующий запрос:

SELECT links.id
  , (
    SELECT COUNT(*)
    FROM stats
    WHERE links.id = stats.parent_id
  ) AS clicks
  , conversions.conversions
  , conversions.conversion_value
FROM links
LEFT JOIN (
  SELECT link_id
    , COUNT(id) AS conversions
    , SUM(conversions.value) AS conversion_value
  FROM conversions
  GROUP BY link_id
) AS conversions ON links.id = conversions.link_id
ORDER BY links.created DESC
3 голосов
/ 13 марта 2010

Я использую подзапрос, чтобы сделать это. Это устраняет проблемы с группировкой. Таким образом, запрос будет выглядеть примерно так:

SELECT COUNT(DISTINCT conversions.id)
...
     (SELECT SUM(conversions.value) FROM ....) AS Vals
2 голосов
/ 19 марта 2010

Как насчет этого:

select l.id, count(s.id) clicks, count(c.id) clicks, sum(c.value) conversion_value
from    (SELECT l.id id, l.created created,
               s.id clicks,  
               c.id conversions,  
               max(c.value) conversion_value                    
        FROM links l LEFT
        JOIN stats s ON l.id = s.parent_id LEFT
        JOIN conversions c ON l.id = c.link_id  
        GROUP BY l.id, l.created, s.id, c.id) t
order by t.created  
1 голос
/ 15 октября 2013

Это поможет, просто разделите сумму на количество идентификаторов разговоров, которые являются дубликатами.

SELECT a.id,
       a.clicks,
       SUM(a.conversion_value/a.conversions) AS conversion_value,
       a.conversions
FROM (SELECT links.id, 
       COUNT(DISTINCT stats.id) AS clicks, 
       COUNT(conversions.id) AS conversions, 
       SUM(conversions.value) AS conversion_value 
      FROM links 
      LEFT OUTER JOIN stats ON links.id = stats.parent_id 
      LEFT OUTER JOIN conversions ON links.id = conversions.link_id 
      GROUP BY conversions.id,links.id
      ORDER BY links.created DESC) AS a
GROUP BY a.id
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...