2016-11-08 79 views
-1

让说我有一个表中存储的调查结果,以及语法看起来是这样的:有没有一种方法可以统计SQL中多列的值?

id | q1 | ..... | q30 | created_at 

created_at是一个时间戳列和所有其他人都是整数的字段。

现在我想根据月份得出调查结果。要做到这一点的一个问题,我有:

SELECT YEAR(created_at) as year, MONTH(created_at) as month, q1, count(*) as occurrence 
    FROM survey_table 
GROUP BY YEAR(created_at), MONTH(created_at), q1 

的回报将是这样的:

year | month| q1 | occurence 
2016 | 11 | 1 | 10 
2016 | 11 | 2 | 15 
2016 | 11 | 3 | 2 
2016 | 10 | 1 | 12 
2016 | 10 | 2 | 2 
2016 | 10 | 3 | 50 

的数据将被传递给我的PHP脚本进行进一步的计算,最后的一些数据显示。

要对30列进行计算,一种方法是针对不同的问题执行此查询30次。我想知道是否有办法做到这一点单查询,以便输出将是这样的:

year | month| q1_1 | q1_2 | q1_3 | q2_1 | q2_2 | q2_3 | ... | q30_1 | q30_2 | q30_3 
2016 | 11 | 10 | 15 | 2 | 2 | 20 | 5 | ... | 5  | 15 | 7  
2016 | 10 | 12 | 2 | 50 | 25 | 27 | 12 | ... | 20 | 24 | 20 

有没有办法在一个查询中这样做吗?如果是,这种表现是否更好?

+1

Google - > SQL Pivoting – sagi

+0

谢谢关键字。 – cytsunny

+0

谷歌,如果你喜欢,但数据显示的问题通常在应用程序级代码(假设可用)最好解决 - 哦,并规范你的设计。 – Strawberry

回答

2

这是您的查询会怎样看:

select 
    year(created_at) as year, 
    month(created_at) as month, 
    count(q1 = 1) as q1_1, 
    count(q1 = 1) as q1_2, 
    count(q1 = 1) as q1_3, 
    count(q1 = 2) as q2_1, 
    ... 
    count(q30 = 3) as q30_3 
from survey_table 
group by year(created_at), month(created_at); 

看来,不过,这将是更好的改变你的表设计:

 
q_type | q_value |created_at 
-------+---------+---------- 
1  | 1  | 2016-10-05 
2  | 3  | 2016-10-05 
3  | 1  | 2016-10-05 
4  | 2  | 2016-10-05 
... 
30  | 1  | 2016-10-05 
... 
29  | 1  | 2016-10-08 
30  | 2  | 2016-10-08 

和您的查询,简直是:

select 
    year(created_at) as year, 
    month(created_at) as month, 
    q_type, 
    q_value, 
    count(*) 
from survey_table 
group by year(created_at), month(created_at), q_type, q_value; 

你会做的格式,即把数据放入一个网格,在PHP中。这更加灵活,因为您的查询不必再知道存在多少个q类型和多少个q值。

+0

的确,这个表格设计对于此操作来说更容易,但是它使得很难从单个调查中获得所有结果。另外,在实际应用中,还有其他类型的问题答案不是整数,所以这种设计是不可能的。 – cytsunny

+0

好的,然后使用第一个查询。但是,您需要事先知道所有可能的q值(在您的示例中为1到3)。或动态构建查询。或者真的写出30个查询,并用'UNION ALL'将它们组合成一个查询。 –

+0

@cytsunny这使得一切都变得简单。你可能需要非常轻微地调整设计,就是这样。 – Strawberry

0

这是我在其他答案的评论中提到的UNION ALL查询。在编写查询时,您不必知道存在什么q值,并且由于UNION ALL只是执行一个查询(以避免不必要的往返)。

由于当前的表格设计,它仍然不是一个超快的查询。

select year(created_at) as year, month(created_at) as month, 'Q1', q1, count(*) as cnt 
from survey_table 
group by year(created_at), month(created_at), q1 
UNION ALL 
select year(created_at) as year, month(created_at) as month, 'Q2', q2, count(*) as cnt 
from survey_table 
group by year(created_at), month(created_at), q2 
UNION ALL 
... 
UNION ALL 
select year(created_at) as year, month(created_at) as month, 'Q30', q30, count(*) as cnt 
from survey_table 
group by year(created_at), month(created_at), q30; 
相关问题