不同行的MYSQL sum()

mak*_*eee 43 mysql sum

我在SQL查询中使用sum()寻求帮助:

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;
Run Code Online (Sandbox Code Playgroud)

我使用DISTINCT是因为我正在"分组",这确保同一行不会被计算多次.

问题是SUM(conversions.value)多次计算每行的"值"(由于分组)

我基本上想要SUM(conversions.value)为每个DISTINCT conversions.id 做.

那可能吗?

Jer*_*NER 77

我可能错了,但据我所知

  • conversions.id是表转换的主键
  • stats.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 
Run Code Online (Sandbox Code Playgroud)

对于每个链接,您获得sizeof([clicks])x sizeof([conversions])行

如您所知,您的请求中的唯一转化次数可以通过a获得

count(distinct conversions.id) = sizeof([conversions])
Run Code Online (Sandbox Code Playgroud)

这个独特的设法删除了笛卡尔积中的所有[点击]行

但显然

sum(conversions.value) = sum([conversions].value) * sizeof([clicks])
Run Code Online (Sandbox Code Playgroud)

在你的情况下,从那以后

count(*) = sizeof([clicks]) x sizeof([conversions])
count(*) = sizeof([clicks]) x count(distinct conversions.id)
Run Code Online (Sandbox Code Playgroud)

你有

sizeof([clicks]) = count(*)/count(distinct conversions.id)
Run Code Online (Sandbox Code Playgroud)

所以我会测试你的请求

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;
Run Code Online (Sandbox Code Playgroud)

让我发布!杰罗姆

  • 你是个天才!在我找到你的答案之前,我几乎认为没有解决方法. (7认同)
  • @ClemensValiente,Jerome的解决方案是正确的,*鉴于conversions.id是转换表*上的唯一列.这可能是一个重要的区别,应该在答案中注明.编辑 - 实际上,它是声明的(conversions.id是表转换的主键) (3认同)
  • 这不是一个足够的答案,因为它除以联接中的总行数,如果父表在联接表中有多个关系,这将产生不需要的结果。 (3认同)

Cle*_*nte 10

Jeromes解决方案实际上是错误的,可能会产生错误的结果!!

sum(conversions.value)*count(DISTINCT conversions.id)/count(*) as conversion_value
Run Code Online (Sandbox Code Playgroud)

我们假设下表

conversions
id value
1 5
1 5
1 5
2 2
3 1
Run Code Online (Sandbox Code Playgroud)

不同id的正确值总和为8. Jerome的公式产生:

sum(conversions.value) = 18
count(distinct conversions.id) = 3
count(*) = 5
18*3/5 = 9.6 != 8
Run Code Online (Sandbox Code Playgroud)

  • 假设conversions.id是一个唯一字段,JOIN不可能产生3行,其中conversions.id = 1且只有1行,其中conversions.id = 2. conversions.id是唯一的假设是隐含的,并且应该明确,但除此之外,公式是可靠的. (4认同)
  • 是“9.6”还是“10.8”。顺便问一下,除了多级子查询或join(子查询)之外,还有其他解决方案吗? (2认同)

Teh*_*ike 7

有关您看到错误数字的原因的解释,请阅读此内容.

我认为Jerome可以处理导致错误的原因.Bryson的查询会起作用,尽管SELECT中的子查询可能效率低下.


Bry*_*son 6

使用以下查询:

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
Run Code Online (Sandbox Code Playgroud)