mySQL:根据另一列的条目

时间:2015-09-11 20:06:42

标签: mysql

我有两个表,一个是用户,一个是user_answers。

用户可以参加调查。该调查有一个主要问题,它决定了以下问题集。如果用户想在完成之前更改问题集,他们可以返回并重新回答。

我遇到的问题是我无法通过MYSQL准确计算结果。到目前为止,我有这个:

select q_id, 
sum(IF(answer like '%A%',1,0)) as A, 
sum(IF(answer like '%B%',1,0)) as B, 
sum(IF(answer like '%C%',1,0)) as C, 
sum(IF(answer like '%D%',1,0)) as D,
sum(IF(answer like '%E%',1,0)) as E,
sum(IF(answer like '%F%',1,0)) as F
from user_answers as t1
join 
(   select distinct id,`date`
    from users
    WHERE finished = 1
    AND date BETWEEN "2015-09-04" AND "2015-09-10"  
) inr
on inr.id=t1.user_id
group by q_id;

这给了我一个漂亮的圆柱标题中所有用户答案的​​计数。 但有些人改变了他们的主要问题(q_id = 0),这个脚本仍在计算他们完成的其他问题集的答案。一个人可以回答所有0-11(存储在同一个表中),但我只想根据问题0总结他们选择的任何块。

如果我用另一种语言伪写这个非常糟糕的话,我会这样做:

foreach(user_id){
  $result = mysqlfetch(select * from user_answers where uid=user_id and q_id=0);
  if(this.q_id(0).response = A){
    //questions 1-4 get added to tally
  }
  if(this.q_id(0).response = B){
    //questions 5-8 get added to tally
  }
  if(this.q_id(0).response = C){
     //questions 9-11 get added to tally
  }
}

但是,在我的例子中,当我们尚未加入时,我根据用户的q_0响应,不知道如何在mysql脚本中有条件地使用SUM。 很抱歉搞砸了桌子,我没想到这是编写剧本的问题。

2 个答案:

答案 0 :(得分:2)

您可以通过其他聚合加入信息:

select t1.q_id, 
       sum(t1.answer like '%A%') as A, 
       sum(t1.answer like '%B%') as B, 
       sum(t1.answer like '%C%') as C, 
       sum(t1.answer like '%D%') as D, 
       sum(t1.answer like '%E%') as E, 
       sum(t1.answer like '%F%') as F
from user_answers t1 join 
     (select distinct id, `date`
      from users
      where finished = 1 and date BETWEEN '2015-09-04' AND '2015-09-10' 
     ) inr
     on inr.id = t1.user_id join
     user_answers q0
     on q0.user_id = t1.user_id and q0.q_id = 0
where (q0.response = 'A' and t1.q_id in (1, 2, 3, 4)) or
      (q0.response = 'B' and t1.q_id in (5, 6, 7, 8)) or
      (q0.response = 'C' and t1.q_id in (9, 10 11)) 
group by t1.q_id;

有些人可能更喜欢将逻辑放在最后on子句而不是where子句中。这完全是一个偏好问题。我希望在where中看到更复杂的逻辑。

注意:您仍然可能无法获得所需的结果。如果用户被记录在多个日期,则inr子查询可能会返回重复项。如果这是一个问题,请从子查询中删除date或将其包含在外部group by中。

答案 1 :(得分:1)

  1. 创建一个表来保存您的计数标准:

    CREATE TABLE answers_to_tally (
      answer0 CHAR(1),
      q_id    INT
    );
    
    INSERT INTO answers_to_tally
      (answer0, q_id)
    VALUES
      ('A', 1), ('A', 2), ('A', 3), ('A', 4),
      ('B', 5), ('B', 6), ('B', 7), ('B', 8),
      ('C', 9), ('C',10), ('C',11)
    ;
    
  2. 通过将该表与您的user_answers表相关联,您可以获得一组(user_id, q_id)对,指出应针对哪些用户计算哪些问题:

    SELECT   a.user_id, t.q_id
    FROM     user_answers     AS a
        JOIN answers_to_tally AS t ON a.answer = t.answer0
                                  AND a.q_id   = 0
    
  3. 然后整个shebang可以像这样放在一起:

    SELECT   q_id,
             SUM(FIND_IN_SET('A', answer) > 0) AS A,
             SUM(FIND_IN_SET('B', answer) > 0) AS B,
             SUM(FIND_IN_SET('C', answer) > 0) AS C,
             SUM(FIND_IN_SET('D', answer) > 0) AS D,
             SUM(FIND_IN_SET('E', answer) > 0) AS E,
             SUM(FIND_IN_SET('F', answer) > 0) AS F
    FROM     user_answers NATURAL JOIN (
               SELECT   a.user_id, t.q_id
               FROM     user_answers     AS a
                   JOIN users            AS u ON a.user_id = u.id
                   JOIN answers_to_tally AS t ON a.answer  = t.answer0
                                             AND a.q_id    = 0
               WHERE    u.finished = 1
                    AND u.date BETWEEN '2015-09-04' AND '2015-09-10'
             ) x
    GROUP BY q_id