SQLite:一起使用avg和case

时间:2014-03-13 22:24:46

标签: sql sqlite case aggregate-functions

我有一个像这样的结构表:

id | date       | count
---+------------+-------
0  | 01-01-2000 | 46
1  | 01-01-2000 | 25
...
0  | 01-02-2000 | 235
1  | 01-02-2000 | 23
...

等等。我想创建一个表(仅用于演示目的,显然没有理由存储这样的数据),它显示了每周每个id的平均值。举个例子,我可以用这样的方式显示一周中每一天的总和

id | sun | mon | tues | wed | thur | fri | sat |
---+-----+-----+------+-----+------+-----+-----+
0  | 146 | 13  | 51   | 123 | ...
1  | 225 | 245 | 2367 | 25  | ...
...
0  | 235 | 246 | 25   | ....
1  | 23  | .....
...

CREATE TABLE dailySum AS
SELECT id,
       SUM(CASE WHEN CAST(strftime('%w', date) AS INTEGER) = 0 THEN count ELSE 0 END) as sun,
       SUM(CASE WHEN CAST(strftime('%w', date) AS INTEGER) = 1 THEN count ELSE 0 END) as mon,
       SUM(CASE WHEN CAST(strftime('%w', date) AS INTEGER) = 2 THEN count ELSE 0 END) as tues,
       SUM(CASE WHEN CAST(strftime('%w', date) AS INTEGER) = 3 THEN count ELSE 0 END) as wed,
       SUM(CASE WHEN CAST(strftime('%w', date) AS INTEGER) = 4 THEN count ELSE 0 END) as thur,
       SUM(CASE WHEN CAST(strftime('%w', date) AS INTEGER) = 5 THEN count ELSE 0 END) as fri,
       SUM(CASE WHEN CAST(strftime('%w', date) AS INTEGER) = 6 THEN count ELSE 0 END) as sat
FROM tableOfImportantThings
GROUP BY id;

然而,如果我用平均值尝试相同的东西,那么我将在计算平均值时包括所有这些零,这显然会显着降低它。我想我可以得到一周中每一天的不同日期的计数,并在稍后的查询中除以该计数,但这样的解决方案似乎过于复杂。我确定我错过了一些明显的东西。有什么建议吗?

1 个答案:

答案 0 :(得分:2)

根据SQLITE文档:

  

avg()函数返回组内所有非NULL X的平均值。看起来不像数字的字符串和BLOB值被解释为0.只要存在至少一个非NULL输入,即使所有输入都是整数,avg()的结果也始终是浮点值。当且仅当没有非NULL输入时,avg()的结果为NULL。

因此,如果将ELSE条件替换为NULL,理论上应该产生正确的结果:

SELECT id,
       AVG(CASE WHEN CAST(strftime('%w', date) AS INTEGER) = 0 THEN count ELSE NULL END) as sun,
       AVG(CASE WHEN CAST(strftime('%w', date) AS INTEGER) = 1 THEN count ELSE NULL END) as mon,
       AVG(CASE WHEN CAST(strftime('%w', date) AS INTEGER) = 2 THEN count ELSE NULL END) as tues,
       AVG(CASE WHEN CAST(strftime('%w', date) AS INTEGER) = 3 THEN count ELSE NULL END) as wed,
       AVG(CASE WHEN CAST(strftime('%w', date) AS INTEGER) = 4 THEN count ELSE NULL END) as thur,
       AVG(CASE WHEN CAST(strftime('%w', date) AS INTEGER) = 5 THEN count ELSE NULL END) as fri,
       AVG(CASE WHEN CAST(strftime('%w', date) AS INTEGER) = 6 THEN count ELSE NULL END) as sat
FROM tableOfImportantThings
GROUP BY id;

更新:好点,CL。根据您的评论,查询可以简化为:

SELECT id,
       AVG(CASE WHEN CAST(strftime('%w', date) AS INTEGER) = 0 THEN count END) as sun,
       AVG(CASE WHEN CAST(strftime('%w', date) AS INTEGER) = 1 THEN count END) as mon,
       AVG(CASE WHEN CAST(strftime('%w', date) AS INTEGER) = 2 THEN count END) as tues,
       AVG(CASE WHEN CAST(strftime('%w', date) AS INTEGER) = 3 THEN count END) as wed,
       AVG(CASE WHEN CAST(strftime('%w', date) AS INTEGER) = 4 THEN count END) as thur,
       AVG(CASE WHEN CAST(strftime('%w', date) AS INTEGER) = 5 THEN count END) as fri,
       AVG(CASE WHEN CAST(strftime('%w', date) AS INTEGER) = 6 THEN count END) as sat
FROM tableOfImportantThings
GROUP BY id;