2012-10-18 3 views
2

je une table qui ressemble à ceci appelé survey_1:joindre des tables et transposer les colonnes et lignes

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

Note: 1X2X1 représente- enquête-id X-id groupe X question-id

J'ai une autre table appelée survey_questions:

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

Le sid (enquête-id), gid (groupe id) et qid (question-id) définir cette question spécifique dans ce t capable

je besoin d'une requête qui me donnera un résultat comme celui-ci:

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

NOTE: Ma base de données contient des milliers de ces colonnes, il serait donc beaucoup de temps pour modifier chaque sondage pour correspondre parfaitement dans ce format.

Quelqu'un peut-il aider? Merci

+0

La raison pour laquelle vous rencontrez des problèmes avec cette requête est que votre colonne 'Answer' dérive de deux colonnes sources différentes. Une solution consiste à UNION ensemble les résultats de deux requêtes SELECT différentes, une pour chaque colonne que vous souhaitez combiner. Mais votre conception de table pourrait probablement utiliser un certain raffinement; Réunir des choses ensemble n'est pas la meilleure façon de résoudre des problèmes comme celui-ci. –

+1

Actuellement, je me sers d'un UNION ............... question de sélection survey_questions rejoindre survey_1 où jeton = 1 ET sid = 1 UNION ALL sélectionnez 1X2X1 comme réponses de survey_1 où jeton = 1 UNION ALL sélectionnez 1X2X2 de survey_1 où jeton = 1 – Merica

+0

qui semble terrible, mais de cette requête, je vous renvoie les questions et les réponses empilées les unes sur les autres dans les colonnes A1-A4 – Merica

Répondre

0

Vous devez utiliser 'UNPIVOT', que MySQL ne prend malheureusement pas en charge. Vous pouvez faire une chose similaire en hardcoding les noms de colonnes (mais vous devez connaître toutes les colonnes à l'avance) comme celle-ci:

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 

Bien sûr, vous pouvez toujours utiliser un langage de script pour générer les noms de colonnes pour vous ... Par exemple, voici une procédure stockée que vous pouvez effectuer:

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 
4

Pouvez-vous modifier le schéma de la table? Parce que la première table, survey_1 est mieux écrite avec une ligne par réponse et avec la clé entière de l'autre table par ligne. Vous aimez cette (ajoutez vos propres index)

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

que les données seraient

------------------------------------------ 
| 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" | 
------------------------------------------ 

Il va être beaucoup plus facile de travailler avec et généralement une meilleure conception.

Voici à quoi il ressemblerait http://sqlfiddle.com/#!2/4f1ca/2

+0

Je donnerais un million de upvotes si je le pouvais. – bobwienholt

+0

Je suis d'accord et ce serait idéal, mais ma base de données est énorme par rapport à mon exemple, donc ce serait un problème de revenir en arrière et de modifier des milliers de lignes et de colonnes. – Merica

+0

Je ne connais pas votre environnement, mais créer deux nouvelles tables et les remplir avec un script externe ne devrait pas prendre trop de temps si vous avez quelques milliers de lignes. –

2

Créer une vue pour chaque enquête. Pour les anciennes enquêtes, un script simple devrait être en mesure de le faire, car de nouvelles enquêtes en font une partie du processus lors de la création de nouvelles enquêtes. Voici comment la vue pourrait chercher 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

Pour construire les vues d'un script serait à peu près faire comme ça.

Trouver toutes les tables pour construire des vues sur en exécutant

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

Pour chaque vue trouver les parties syndicales en exécutant ce pour sa 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]+$'; 

Extraire les parties numériques et de les utiliser lorsque l'on compare avec Sid, Gid et Qid.

Ce script peut également être utilisé pour remplir de nouvelles tables appropriées.

Questions connexes