SQL group by和count固定列值

时间:2013-01-14 17:24:35

标签: sql count group-by

我在SQL(MySQL)中的数据导入脚本中遇到问题,我需要按行键入GROUP来计算每种类型的行数。到目前为止,这不是一个真正的问题,因为我知道我可以做到:

SELECT 
  data.type, 
  COUNT(data.type) 
FROM data 
GROUP BY data.type;

所以,通过这样做,我得到了结果:

 -------------- --------------------- 
| type         | COUNT(data.type)    |
|--------------|---------------------|
| 0            |                   1 |
| 1            |                  46 |
| 2            |                  35 |
| 3            |                 423 |
| 4            |                  64 |
| 5            |                  36 |
| 9            |                   1 |
 -------------- ---------------------

我知道在 type 列中,值总是在0到9的范围内,就像上面的结果一样。因此,我不仅要列出表格内容中的现有值,还要列出缺少的类型值,并将其COUNT值设置为0。

根据上述查询结果,预期结果为:

 -------------- --------------------- 
| type         | COUNT(data.type)    |
|--------------|---------------------|
| 0            |                   1 |
| 1            |                  46 |
| 2            |                  35 |
| 3            |                 423 |
| 4            |                  64 |
| 5            |                  36 |
| 6            |                   0 |
| 7            |                   0 |
| 8            |                   0 |
| 9            |                   1 |
 -------------- --------------------- 

我可以在GROUP / COUNT-1表内容之前巧妙地插入每种类型的一行,在INSERT上标记一些其他列以便能够删除这些行。因此,我的导入脚本的步骤将更改为:

  1. TRUNCATE 表; (如果表中有旧数据,我不能安全地导入新内容)
  2. INSERT “控制”行;
  3. 将数据填入表格;
  4. GROUP / COUNT-1 表格内容;
  5. 删除“控制”行; (所以我仍然可以使用表格内容)
  6. 其他工作;
  7. 但是,我正在寻找一种更清洁的方法来达到预期的结果。如果可能的话,单个查询,没有一堆JOIN。

    我将不胜感激任何建议或意见。非常感谢你!

    修改

    我要感谢有关创建表以存储所有类型以加入JOIN的答案。它真的解决了这个问题。我的方法也解决了这个问题,但是它存储了类型,就像你一样。

    所以,根据收到的答案和我想要的范围,我有“另一个”问题,只是一个澄清......是否有可能通过一些不会创建新表和/或创建一个新表的MySQL命令达到预期结果插入这些类型吗?

    我没有看到任何问题,实际上,在解决我存储类型的问题...我只是想找到一个简化的命令...类似于'最佳实践'......某种过滤器。 ..因为我可以跑:

    GROUP BY data.type(0,1,2,3,4,5,6,7,8,9)
    

    它可以返回这些过滤的值。

    我真的很有兴趣学习这样一个命令,如果它确实存在/是可能的。

    再次,非常感谢你!

4 个答案:

答案 0 :(得分:0)

假设您有一个包含所有有效类型的types表:

SELECT t.type, 
       COUNT(data.type) 
FROM data join types t on data.type = t.type
GROUP BY t.type
order by t.type

您应该包含明确的order by,而不是依赖于group by来按特定顺序生成结果。

答案 1 :(得分:0)

最简单的方法是创建一个包含所有type值的表,然后在获取计数时加入该表:

select t.type,
  count(d.type)
from types t
left join data d
  on t.type = d.type
group by t.type

请参阅SQL Fiddle with demo

或者您可以使用以下内容:

select t.type,
  count(d.type)
from
(
  select 0 type
  union all
  select 1 
  union all
  select 2
  union all
  select 3
  union all
  select 4
  union all
  select 5 
  union all
  select 6
  union all
  select 7
  union all
  select 8
  union all
  select 9 
) t
left join data d
  on t.type = d.type
group by t.type

请参阅SQL Fiddle with Demo

答案 2 :(得分:0)

一个选项是使用值为0-9的静态数字表。不确定这是否是最优雅的方法,如果您使用的是SQL Server,我可以考虑另一种方法。

尝试这样的事情:

SELECT 
  numbers.number, 
  COUNT(data.type) 
FROM numbers 
left join data 
  on numbers.number = data.type
GROUP BY numbers.number;

SQL Fiddle

答案 3 :(得分:0)

好的......我想我找到了!谢谢你们!!!我接受了自己的答案。

我同意@GordonLinoff的评论,即最佳做法是指存储类型值并对其进行描述,以便您可以保持简洁/易懂的数据库和查询。

但是,据我所知,如果你有一些可能是无关信息的数据,最好以其他方式处理它而不是存储它。

所以,我开发了这个查询:

SELECT 
  SUM(IF(data.type = 0, 1, 0)) AS `0`, 
  SUM(IF(data.type = 1, 1, 0)) AS `1`, 
  SUM(IF(data.type = 2, 1, 0)) AS `2`, 
  SUM(IF(data.type = 3, 1, 0)) AS `3`, 
  SUM(IF(data.type = 4, 1, 0)) AS `4`, 
  SUM(IF(data.type = 5, 1, 0)) AS `5`, 
  SUM(IF(data.type = 6, 1, 0)) AS `6`, 
  SUM(IF(data.type = 7, 1, 0)) AS `7`, 
  SUM(IF(data.type = 8, 1, 0)) AS `8`, 
  SUM(IF(data.type = 9, 1, 0)) AS `9` 
FROM data;

不是那么快,优化和美观的查询,但是对于我将管理的数据大小(每次输入少于100.000行),它“手动”执行GROUP / COUNT作业,在一个共同的开发人员中运行0.13秒机。

它与我的预期结果不同,只是选择行和列的方式 - 而不是10行,2列,我有1行,10列,标记匹配类型。此外,由于我们对类型值进行了标准化(并且我们不会确定地更改它),这给了它一个名称和描述,我现在能够使用类型名称作为列标签,而不是连接到具有类型信息的表来选择结果中的第三列(实际上,这并不重要,因为它是基于某些标准的导入脚本)。

非常感谢你的帮助!