如何从MySQL获取高级统计数据?

Ari*_*Ari 0 php mysql

嗨,

我有一个非常大的MySQL数据库,其表格的结构如下:
在exmaple中,DATE采用unix时间戳格式.所以它需要转换为正常的美国日期格式,这只是我的数据库中的一些记录.

ID DATE REG_TYPE
--------------------------------------
1 1251917888 0
2 1251917888 1
3 1251917888 1
4 1251917888 0
5 1251917888 2
6 1251917888 3
7 1251917888 2
8 1251917888 4
9 1251917888 0
10 1251917888 0

问题是我想获得按日期排序的每个REG_TYPE的计数.下面显示了我想得到的内容:

DATE REGTYPE(0)REGTYPE(1)REGTYPE(2)REGTYPE(3)REGTYPE(4)
----------------- -------------------------------------------------- -------------------------------
xxxx 4 2 2 1 1
xxxx x x x x x


我想在每个日期都得到这个数据库就像每个日期的摘要一样.


任何人都可以建议一个可能的解决方案吗?在从MYSQL获取数据后,我必须将此输出转换为PHP中的数组.在PHP中不使用循环的原因是数据库太大并且会导致超时.

最好的祝福
 

dcr*_*sta 5

您想要做的是一个数据透视操作,SQL语法不直接支持它.但是,它并不太复杂,概念上涉及两个步骤:

  1. 将数据"爆炸"成许多列,原始数据集中每行一行.这通常使用CASE WHEN ... ELSE ... END或偶尔使用函数(如oracle中的decode())来完成.我将在下面的示例中使用CASE WHEN,因为它对大多数RDBMS都同样有效
  2. 使用GROUP BY和聚合函数(SUM,MIN,MAX等)将许多行折叠到所需的输出行集中.

我正在使用此数据集作为示例:

mysql> select * from foo;
+----+------------+----------+
| id | thedate    | reg_type |
+----+------------+----------+
|  1 | 1251917888 |        0 | 
|  2 | 1251917888 |        1 | 
|  3 | 1251917888 |        1 | 
|  4 | 1251917888 |        0 | 
|  5 | 1251917888 |        2 | 
|  6 | 1251917888 |        3 | 
|  7 | 1251917888 |        2 | 
|  8 | 1251917888 |        4 | 
|  9 | 1251917888 |        0 | 
| 10 | 1251917888 |        0 | 
| 11 | 1251831488 |        1 | 
| 12 | 1251831488 |        2 | 
| 13 | 1251831488 |        2 | 
| 14 | 1251831488 |        1 | 
| 15 | 1251831488 |        3 | 
| 16 | 1251831488 |        4 | 
| 17 | 1251831488 |        3 | 
| 18 | 1251831488 |        5 | 
| 19 | 1251831488 |        1 | 
| 20 | 1251831488 |        1 | 
+----+------------+----------+
Run Code Online (Sandbox Code Playgroud)

第1步是"炸毁"数据集:

select id
     , thedate
     , case when reg_type = 0 then 1 else 0 end as reg_type_0
     , case when reg_type = 1 then 1 else 0 end as reg_type_1
     , case when reg_type = 2 then 1 else 0 end as reg_type_2
     , case when reg_type = 3 then 1 else 0 end as reg_type_3
     , case when reg_type = 4 then 1 else 0 end as reg_type_4
     , case when reg_type = 5 then 1 else 0 end as reg_type_5
  from foo;
Run Code Online (Sandbox Code Playgroud)

这使:

+----+------------+------------+------------+------------+------------+------------+------------+
| id | thedate    | reg_type_0 | reg_type_1 | reg_type_2 | reg_type_3 | reg_type_4 | reg_type_5 |
+----+------------+------------+------------+------------+------------+------------+------------+
|  1 | 1251917888 |          1 |          0 |          0 |          0 |          0 |          0 | 
|  2 | 1251917888 |          0 |          1 |          0 |          0 |          0 |          0 | 
|  3 | 1251917888 |          0 |          1 |          0 |          0 |          0 |          0 | 
|  4 | 1251917888 |          1 |          0 |          0 |          0 |          0 |          0 | 
|  5 | 1251917888 |          0 |          0 |          1 |          0 |          0 |          0 | 
|  6 | 1251917888 |          0 |          0 |          0 |          1 |          0 |          0 | 
|  7 | 1251917888 |          0 |          0 |          1 |          0 |          0 |          0 | 
|  8 | 1251917888 |          0 |          0 |          0 |          0 |          1 |          0 | 
|  9 | 1251917888 |          1 |          0 |          0 |          0 |          0 |          0 | 
| 10 | 1251917888 |          1 |          0 |          0 |          0 |          0 |          0 | 
| 11 | 1251831488 |          0 |          1 |          0 |          0 |          0 |          0 | 
| 12 | 1251831488 |          0 |          0 |          1 |          0 |          0 |          0 | 
| 13 | 1251831488 |          0 |          0 |          1 |          0 |          0 |          0 | 
| 14 | 1251831488 |          0 |          1 |          0 |          0 |          0 |          0 | 
| 15 | 1251831488 |          0 |          0 |          0 |          1 |          0 |          0 | 
| 16 | 1251831488 |          0 |          0 |          0 |          0 |          1 |          0 | 
| 17 | 1251831488 |          0 |          0 |          0 |          1 |          0 |          0 | 
| 18 | 1251831488 |          0 |          0 |          0 |          0 |          0 |          1 | 
| 19 | 1251831488 |          0 |          1 |          0 |          0 |          0 |          0 | 
| 20 | 1251831488 |          0 |          1 |          0 |          0 |          0 |          0 | 
+----+------------+------------+------------+------------+------------+------------+------------+
Run Code Online (Sandbox Code Playgroud)

接下来,我们在每个日期的输出中折叠为一行,并将每个reg_type_*列相加,使用或初始查询作为内联视图(也称为"子查询"):

select thedate
     , sum(i.reg_type_0) as reg_type_0
     , sum(i.reg_type_1) as reg_type_1
     , sum(i.reg_type_2) as reg_type_2
     , sum(i.reg_type_3) as reg_type_3
     , sum(i.reg_type_4) as reg_type_4
     , sum(i.reg_type_5) as reg_type_5
  from (
         select id
              , thedate
              , case when reg_type = 0 then 1 else 0 end as reg_type_0
              , case when reg_type = 1 then 1 else 0 end as reg_type_1
              , case when reg_type = 2 then 1 else 0 end as reg_type_2
              , case when reg_type = 3 then 1 else 0 end as reg_type_3
              , case when reg_type = 4 then 1 else 0 end as reg_type_4
              , case when reg_type = 5 then 1 else 0 end as reg_type_5
           from foo
       ) i
 group by thedate
 order by thedate asc;
Run Code Online (Sandbox Code Playgroud)

(另请注意,您可以将这两个查询合并为一个,但为了清楚起见,我在这里单独显示它们;至少在MySQL中,这似乎导致更简单的执行计划,这通常意味着更快的执行 - 一如既往,测试你在现实数据集上的SQL性能,不要相信我的话!)

这给了我们:

+------------+------------+------------+------------+------------+------------+------------+
| thedate    | reg_type_0 | reg_type_1 | reg_type_2 | reg_type_3 | reg_type_4 | reg_type_5 |
+------------+------------+------------+------------+------------+------------+------------+
| 1251831488 |          0 |          4 |          2 |          2 |          1 |          1 | 
| 1251917888 |          4 |          2 |          2 |          1 |          1 |          0 | 
+------------+------------+------------+------------+------------+------------+------------+
Run Code Online (Sandbox Code Playgroud)

这是期望的结果.您可以使用MySQL函数FROM_UNIXTIME将日期转换为DATE,并且在第2部分查询中执行此操作可能是最有效的(评估函数的次数较少,并且对整数组进行比较,而不是DATE - 不确定这在MySQL中是否真的有任何不同).