Mysql WHERE IN()子句必须对重复事件进行求和

时间:2014-08-06 19:32:17

标签: mysql

我有一个以逗号分隔的ID列表,我必须在mysql(Percona Xtra DB)中的IN()子句中使用,类似于:

SELECT sum(p_views) as total_views FROM table WHERE id IN (1,1,3,5,5,5,7)

在上面的示例中,id 1和5只会被求和一次,而不是实际出现的次数。重复数量未知,范围从2到20000.

我如何让mysql将它们视为唯一数字,并相应地对它们求和,无论它们是否都是唯一的,或者列表是否由单个ID组成,20000次?

1 个答案:

答案 0 :(得分:1)

这不能用IN ()谓词完成。这只会检查给定行是否满足谓词;它不会复制"返回的行。

获得"重复"返回的行(因此值可以在SUM()聚合中累积),您需要另一个行源。

一种选择是对内联视图使用JOIN操作,而不是IN()列表谓词。

SELECT SUM(t.p_views) AS total_views
  FROM table t
  JOIN 
     ( SELECT           1 AS id 
       UNION ALL SELECT 1
       UNION ALL SELECT 1
       UNION ALL SELECT 3
       UNION ALL SELECT 5
       UNION ALL SELECT 5
       UNION ALL SELECT 5
       UNION ALL SELECT 7
     ) c
    ON c.id = t.id

另一个(可能更有效)选项(如果有很多重复值)将使用" count"而不是重复这些值,并乘以,例如

SELECT SUM(t.p_views*c.cnt) AS total_views
  FROM table t
  JOIN
     ( SELECT           1 AS id, 2 AS cnt 
       UNION ALL SELECT 3      , 1
       UNION ALL SELECT 5      , 3
       UNION ALL SELECT 7      , 1
     ) c
    ON c.id = t.id

如果此信息已在另一个行源中可用,则可以通过在查询中使用该行源(如果有适当的索引可用)来提高性能,并避免产生杂乱的信息。硬编码" UNION ALL内联视图,不会被编入索引(除非Percona已经为内联视图实现了索引。)

我确定还有其他方法。

但最重要的是,它不能用IN()列表谓词完成。来自查询的结果:

WHERE id IN (1)

与查询结果相同:

WHERE id IN (1,1,1,1)

因为,对于每一行,这两个谓词都将评估为TRUEFALSENULL。没有办法返回"次数"与IN()比较相匹配的商品。