SQL查询帮助:有效地根据列的组合获取计数

时间:2014-08-26 20:44:26

标签: mysql sql performance

我有一个表(变量(无限种类),attr(正好3个不同的属性),日期,状态(只能是0,1或2)):

 ------------------------------------
| Variable | Attr |   Date   | State |
|------------------------------------|
|    V1    |  A1  |01/01/14  |  0    |      
|    V1    |  A1  |01/02/14  |  2    |           
|    V1    |  A1  |01/03/14  |  1    |     
|    V1    |  A1  |01/04/14  |  2    |      
|    V1    |  A2  |01/01/14  |  1    |      
|    V1    |  A2  |01/02/14  |  0    |           
|    V1    |  A2  |01/03/14  |  1    |     
|    V1    |  A2  |01/04/14  |  1    |  
|    V1    |  A3  |01/01/14  |  0    |      
|    V1    |  A3  |01/02/14  |  0    |           
|    V1    |  A3  |01/03/14  |  1    |     
|    V1    |  A3  |01/04/14  |  2    |  
|    V2    |  A1  |01/01/14  |  2    |      
|    V2    |  A1  |01/02/14  |  1    |           
|    V2    |  A1  |01/03/14  |  2    |     
|    V2    |  A1  |01/04/14  |  1    |      
|    V2    |  A2  |01/01/14  |  1    |      
|    V2    |  A2  |01/02/14  |  2    |           
|    V2    |  A2  |01/03/14  |  1    |     
|    V2    |  A2  |01/04/14  |  0    |  
|    V2    |  A3  |01/01/14  |  1    |      
|    V2    |  A3  |01/02/14  |  0    |           
|    V2    |  A3  |01/03/14  |  2    |     
|    V2    |  A3  |01/04/14  |  1    |  
|    V3    |  A1  |01/01/14  |  1    |      
|    V3    |  A1  |01/02/14  |  2    |           
|    V3    |  A1  |01/03/14  |  1    |     
|    V3    |  A1  |01/04/14  |  1    |      
|    V3    |  A2  |01/01/14  |  1    |      
|    V3    |  A2  |01/02/14  |  0    |           
|    V3    |  A2  |01/03/14  |  0    |     
|    V3    |  A2  |01/04/14  |  2    |  
|    V3    |  A3  |01/01/14  |  1    |      
|    V3    |  A3  |01/02/14  |  0    |           
|    V3    |  A3  |01/03/14  |  2    |     
|    V1    |  A3  |01/04/14  |  1    | 
|    .     |  .   |.         |  .    |
|    Vn    |  An  |n         |  n    | 
|----------|------|----------|-------|

我想要的输出(音符计数是此示例的完全随机值):

------------------------------------
| Variable | Attr | Count| State |
 ------------------------------------
|    V1    |  A1  | 50   |  0    |      
|    V1    |  A1  | 24   |  1    | 
|    V1    |  A1  | 22   |  2    |                
|    V1    |  A2  | 1    |  0    |       
|    V1    |  A2  | 0    |  1    |
|    V1    |  A2  | 15   |  2    |      
|    V1    |  A3  | 68   |  0    |
|    V1    |  A3  | 9    |  1    | 
|    V1    |  A3  | 34   |  2    |       
|    V2    |  A1  | 10   |  0    |               
|    V2    |  A1  | 0    |  1    |
|    V2    |  A1  | 25   |  2    |                   
|    V2    |  A2  | 48   |  0    |     
|    V2    |  A2  | 96   |  1    | 
|    V2    |  A2  | 14   |  2    |             
|    V2    |  A3  | 12   |  0    |     
|    V2    |  A3  | 3    |  1    |
|    V2    |  A3  | 0    |  2    |              
|    V3    |  A1  | 4    |  0    |     
|    V3    |  A1  | 5    |  1    |
|    V3    |  A1  | 8    |  2    |                     
|    V3    |  A2  | 19   |  0    |     
|    V3    |  A2  | 95   |  1    | 
|    V3    |  A2  | 26   |  2    |                   
|    V3    |  A3  | 4    |  0    |     
|    V3    |  A3  | 85   |  1    |
|    V3    |  A3  | 50   |  2    |   
|    .     |  .   |.     |  .    |
|    Vn    |  An  |n     |  n    | 
|----------|------|------|-------|

我要做的第一件事就是选择一个变量+ attr + state组合,我想把我的查询作为基础。所以我要说我选择V2 + A3 + 2.接下来我想去找所有行的日期,其中var = V2,attr = A3,state = 2.接下来我需要仔细检查这些日期并计算所有日期其他var + attr +状态组合。例如,如果V2 + A3 + 2发生在01/01/14,02/06 / 14,02 / 07 / 14,04 / 09/14和05/03/14,它将通过这些上的所有其他变量日期并将每个var + attr +状态组合的出现次数相加。因此输出将对每个var + attr +状态组合进行分组,并且每个组合的计数都会显示。

要完成此操作,我使用的是查询:

SELECT  m2.variable, m2.attr, m2.state, COUNT(*)
FROM    mytable m1
JOIN    mytable m2
ON      m2.date = m1.date
WHERE   (m1.variable, m1.attr, m1.state) = ('V2', 'A3', 2)
GROUP BY
        m2.variable, m2.attr, m2.state

所以这个查询实际上返回了我选择的变量+属性+状态组合的计数。所以这只是一个组合,但我想得到可能组合的计数(~20,000个不同的变量x 5个不同的属性x 3个不同的状态)。我的初始方法是编写一个脚本来替换组合变量(例如( m1.variable,m1.attr,m1.state)=(SUB_VAR1,SUB_VAR2,SUB_VAR3))并简单地遍历所有组合并返回计数(我只对每个计数的最高20个计数感兴趣)。我想最初这可能需要几个小时才能完成。问题是查询非常非常慢,每个组合运行大约45秒。这里使用的表有大约15M - 20M行(~20,000个变量x5个属性x3个状态×60天),表格正在连接,因此要处理的行数很多,需要几个月的处理时间。我的主键是Variable + Attr + Date,当然还有一个索引。我曾尝试创建一个重复的表,但是使用MEMORY引擎希望它能加快进程,但它只会将速度提高大约5-10秒。我对查询性能不强,但我尝试了其他一些查询,但是他们没有帮助。我有需要,我想到一个更有效的查询,甚至可能完整的表重新设计?我已经尝试了各种似乎不起作用的东西,如何以高效的方式实现我需要的任何输入将非常感激。

3 个答案:

答案 0 :(得分:0)

据我所知,您希望将查询基于所有组合。获取这些组合的日期,然后计算具有该日期的其他组合的数量..如果那是真的那么这将做你想要的。

SELECT  Variable , Attr , COUNT(*) , State
FROM mytable 
WHERE date IN
(   SELECT date 
    FROM mytable  
    GROUP BY variable, attr, state
)
GROUP BY variable, attr, state

答案 1 :(得分:0)

使用cross join生成所有组合,然后使用您的查询:

SELECT v.variable, a.attr, s.state, COUNT(m2.date)
FROM (select distinct variable from mytable) v cross join
     (select distinct attr from mytable) a cross join
     (select distinct state) from mytable) s left join
     mytable m
     on m.variable = v.variable and m.attr = a.attr and m.state = v.state left join
     mytable m2
     ON m2.date = m1.date and (m1.variable, m1.attr, m1.state) = ('V2', 'A3', 2)
GROUP BY v.variable, a.attr, s.state;

答案 2 :(得分:0)

你能否证实这给出了你期待的答案

select
    bases.variable as basis_v,
    bases.attr as basis_a,
    bases.state as basis_s,
    counts.variable,
    counts.attr,
    counts.state,
    count(*) as count
from 
    mytable bases
        inner join
    mytable counts
        on bases.date = counts.date
group by
    bases.variable,
    bases.attr,
    bases.state,
    counts.variable,
    counts.attr,
    counts.state
order by
    bases.variable,
    bases.attr,
    bases.state,
    counts.variable,
    counts.attr,
    counts.state;

Example SQLFiddle

另请注意,我未包含v, a, s的所有组合,仅包括实际发生的组合。

由于自我加入,这仍然会相当慢,但至少你可以一次性获得所有结果。但是,请记住,它们可能高达20,000 x 20,000!