2

我有一个看起来像这样的表,称为survey_1:

================================================
|id  | token  |     1X2X1     |    1X2X2       |
=====+========+===============+================|
| 1  |   1    |    YES        | Justin Beiber  |
|----+--------+---------------+----------------|
| 2  |   1    |    YES        | Britney Spears |
|----+--------+---------------+----------------|

注意:1X2X1 代表-survey-id X group-id X question-id

我有另一个表叫survey_questions:

===============================================================
|sid |   gid  |   qid  |             question                 |
=====+========+===============+===============================|
| 1  |  2     |    1   |  Do you listen to music?             |
|----+--------+-----------------------------------------------|
| 1  |  2     |    2   |  Who is your favorite music artists? |
|----+--------+-----------------------------------------------|

sid (survey-id)、gid (group-id) 和 qid(question-id) 定义此表中的特定问题

我需要一个查询,它会给我这样的结果:

======================================================
|           Question                  |   Answer     |
=========+===========+===============================|
| Do you listen to music?             |    YES       |            
|----------------------------------------------------|
| Who is your favorite music artists? | Justin Beiber| 
|----------------------------------------------------|

注意:我的数据库包含数千个这样的列,因此编辑每个调查以完全匹配这种格式会非常耗时。

有人可以帮忙吗?谢谢

4

3 回答 3

4

Can you change the table schema? Cause that first table, survey_1 is better written with one row per answer and with the entire key of the other table per row. Like this (add your own indexes)

create table survey_1 (
  id int,
  token int,
  sid int,
  gid int,
  qid int,
  answer varchar(255)
)

Than the data would be

------------------------------------------
| 1 | 1 | 1 | 2 | 1 | "YES"              |
| 1 | 1 | 1 | 2 | 2 | "Justin Beiber"    |
| 2 | 1 | 1 | 2 | 1 | "YES"              |
| 2 | 1 | 1 | 2 | 2 | "Britney Spears"   |
------------------------------------------

It's going to be much easier to work with and generally a better design.

Here is how it would look http://sqlfiddle.com/#!2/4f1ca/2

于 2012-10-18T19:26:35.383 回答
2

Create a view for each survey. For the old surveys a simple script should be able to do it, for new surveys make it a part of the process when creating new surveys. This is how the view could look for survey_1

create or replace view v_survey_1 as
select id, question, 1X2X1 as answer 
  from question
  join survey_1 s
 where sid = 1
   and gid = 2
   and qid = 1
union
select id, question, 1X2X2 
  from question
  join survey_1 s
 where sid = 1
   and gid = 2
   and qid = 2
;

http://sqlfiddle.com/#!2/63aee/1

To build the views a script would roughly do like this.

Find all tables to build views on by running

select table_name 
 from information_schema.tables 
where table_schema = 'test' 
  and table_name like 'survey\_%';

For each view find the union parts by running this for its table

select column_name
  from information_schema.columns 
 where table_name = 'survey_1' 
   and column_name regexp '^[0-9]+X[0-9]+X[0-9]+$';

Extract the number parts and use them when comparing with sid, gid and qid.

This script could also be used to populate new proper tables.

于 2012-10-18T20:23:50.837 回答
0

您需要使用 MySQL 不支持的“UNPIVOT”。您可以通过硬编码列名(但您需要提前知道所有列)来做类似的事情,如下所示:

SELECT survey_questions.Question,
       CASE survey_questions.qid 
         WHEN 1 THEN survey_1.`1X2X1`
         WHEN 2 THEN survey_1.`1X2X2`
         WHEN 3 THEN survey_1.`1X2X3`
         WHEN 4 THEN survey_1.`1X2X4`
       // ...
       END as Answer
FROM survey_questions
JOIN survey_1 
  ON survey_questions.qid = survey_1.id
  AND survey_questions.gid = survey_1.token_id
WHERE survey_questions.sid = 1

Of course, you can always use some scripting language to generate the column names for you... For example, here is a stored procedure you can make:

CREATE PROCEDURE 'get_qa_for_survey'
(
  IN surveyId INT
)
BEGIN
  DECLARE query1 TEXT; 
  SET @tableName = 'survey_' + surveyId;
  SET query1 = 'SELECT survey_questions.Question,
       CASE survey_questions.qid ';

  DECLARE col_names CURSOR FOR
    SELECT column_name
    FROM INFORMATION_SCHEMA.COLUMNS
    WHERE table_name = @tableName
    AND (column_name LIKE surveyId +'X%');
    ORDER BY ordinal_position;

  select FOUND_ROWS() into num_rows;

  SET i = 1;
  the_loop: LOOP    
     IF i > num_rows THEN
        CLOSE col_names;
        LEAVE the_loop;
     END IF;

     FETCH col_names 
     INTO col_name;     
     SET query1 = query1 + ' WHEN ' + i + ' THEN ' + @tableName + '.' + col_name
     SET i = i + 1;  
  END LOOP the_loop;

  SET query1 = query1 + ' END as Answer
    FROM survey_questions
    JOIN ' + @tableName + '
      ON survey_questions.qid = ' + @tableName + '.id
      AND survey_questions.gid = ' + @tableName + '.token_id
    WHERE survey_questions.sid = ' + surveyId; 


  SET @Sql = query1;        
  PREPARE STMT FROM @Sql; 
  EXECUTE STMT; 
  DEALLOCATE PREPARE STMT;
END
于 2012-10-18T19:23:47.930 回答