【问题标题】:Pivot table in a specific way in MySQL在 MySQL 中以特定方式数据透视表
【发布时间】:2016-06-02 14:39:56
【问题描述】:

还有其他数据透视表问题,但我似乎找不到我的问题的答案。

这是我的桌子

ID    QUESTION       ANSWER       RECORDID      SORTORDER
1     Question 1     Answer 1.1   123456        1
2     Question 2     Answer 2.1   123456        2
3     Question 3     Answer 3.1   123456        3
4     Question 1     Answer 1.2   654321        1
5     Question 2     Answer 2.2   654321        2
6     Question 3     Answer 3.2   654321        3

等等

我想通过查询将其输出到:

Question 1    Question 2    Question 3
Answer 1.1    Answer 2.1    Answer 3.1
Answer 1.2    Answer 2.2    Answer 3.2

简而言之,问题列包含不唯一的问题(在此演示中有 2 个条目(请参阅 RECORDID)),因此需要按排序顺序对它们进行分组和排序。 RECORDID 始终是唯一的

我看到了一些枢轴/非枢轴示例,但无法理解它。 有人可以帮我解决这个问题吗?

【问题讨论】:

  • 你需要unpivot
  • 嗨,Maciej Los,嗯,我不确定。检查我编辑的问题。
  • 您已经使用 PHP 进行了标记,因此请在此处处理事物的表示方面。显然,RECORDID 并不总是唯一的!
  • 另外,我不明白同一个问题中的两条记录如何占据相同的排序顺序。
  • @Strawberry 你是对的,我解释错了。当我说它是唯一的时,我的意思是每个条目(在这种情况下,3 个问题加起来是 1 个条目)都有 1 个唯一的 RECORD ID(ID 为 123456 的条目和 654321 的条目)。

标签: php mysql sql pivot


【解决方案1】:

这应该可以解决问题。在内部查询中,您只能获得特定问题的答案,而在外部查询中,当您按 recordid 分组时,您会摆脱空值...尝试仅运行内部查询以了解想法。

select  
  max(q.Question1),
  max(q.Question2),
  max(q.Question3) FROM (SELECT     
                         recordid,
                         case when question = 'Question 1' then answer else null end as Question1, 
                         case when question = 'Question 2' then answer else null end as Question2, 
                         case when question = 'Question 3' then answer else null end as Question3 FROM questions) q group by q.recordid

如果您有任何问题,请告诉我!

编辑:您的评论增加了另一个级别的复杂性:) 现在我知道我们如何使用该排序顺序列...我们需要一个内部查询来获取问题及其排序顺序。然后按每个排序顺序获取答案,然后按记录 id 分组以过滤掉空值并获得所需的结果。请试试这个,让我知道它是怎么回事... select 语句中的问题数必须等于问题最多的表单中的问题数 - 我输入 8 只是为了向您展示这不应该限制你。现在您将不依赖于问题名称 - 只依赖于排序编号。最好有排序顺序 - 否则您必须为每个记录 ID 生成一个行号...

SET @rank=0; SET @id:=0; select recordid, max(qq.question1) as 'Question 1', max(qq.question2) as 'Question 2', max(qq.question3) as 'Question 3', max(qq.question4) as 'Question 4', max(qq.question5) as 'Question 5', max(qq.question6) as 'Question 6', max(qq.question7) as 'Question 7', max(qq.question8) as 'Question 8' FROM ( SELECT recordid, case when q.rownumber = 1 then CONCAT(question,': ', answer) else null end as question1, case when q.rownumber = 2 then CONCAT(question,': ', answer) else null end as question2, case when q.rownumber = 3 then CONCAT(question,': ', answer) else null end as question3, case when q.rownumber = 4 then CONCAT(question,': ', answer) else null end as question4, case when q.rownumber = 5 then CONCAT(question,': ', answer) else null end as question5, case when q.rownumber = 6 then CONCAT(question,': ', answer) else null end as question6, case when q.rownumber = 7 then CONCAT(question,': ', answer) else null end as question7, case when q.rownumber = 8 then CONCAT(question,': ', answer) else null end as question8 FROM( select recordid, question, answer, sortorder, @rank:=CASE WHEN @id=recordid THEN @rank+1 ELSE 1 END as rownumber, @id:=recordid from questions order by recordid, sortorder ) q )qq GROUP BY recordid

【讨论】:

  • 您好 Koshera,非常感谢您尝试找到解决方案。问题是问题永远无法预测,因此查询中的“问题 1”将不起作用。这就是发生的情况:此表存储使用在线表单提交此数据的人的条目(一组具有 1 个特定记录 ID 的问题),但 QUESTIONS 列中的问题是重复的(表单具有一组特定的问题) 但用户也可以填写进入此表的其他表格,因此会出现不可预测的问题。
  • 请查看编辑 - 我认为现在应该一切都好!让我知道进展如何:)
  • 嗨,差不多了!仍然存在 2 个问题: 1. 输出显示问题 1、问题 2 等,但不是实际问题(例如:名字(问题 1)、姓氏(问题 2)等)。我只在不知道问题的情况下得到答案。 2. sortorder只能用于order by,不能用于matching。由于表单不时被编辑,排序顺序可能会变大(100 或更多)。此外,它必须按问题分组,否则将显示多个问题。例如,名字 2 个条目将输出 2x 名字希望您对此有解决方案,我已经非常感谢您了!
  • 如果太复杂,也许这是一个不错的选择(PHP 和 MySQL 的组合):先用 group by 选择问题,而不是 "is Question 1" 用问题替换它PHP while 循环然后进行查询?
  • 好的,所以我们需要在内部查询中使用两个参数(@id 和@rank)定义一个行号,并使用排序顺序...根据您的其他说明,因为您有混合数据(问题名称不同 - 即不同形式的每个位置的问题名称可能不同) - 您不能将它们作为数据透视表中的列标题。相反,您可以将它们连接到答案中。这样,您将在枢轴中看到位置、问题名称和答案,但我不确定这是否有帮助。查看更新后的查询 - 希望对您有所帮助...
【解决方案2】:

谢谢大家(尤其是 Koshera!),经过一些调整,我让它按我想要的方式工作。

这是总代码(原始,概念证明;))。 函数 processQuery 是一个带有参数化查询的 try / catch PDO 执行(参见 ? 占位符,“原始” $i 应该没有问题吗?)。

<div class="database-container">
<table border="0" cellspacing="0" cellpadding="7">
<tr>

<?php

// get all questions and group them so we only get unique questions
$getQuestions = processQuery("SELECT ansr_question FROM forms_123456 WHERE is_answer=1 and ansr_type != 'text' GROUP BY ansr_question ORDER BY ansr_sortorder ASC",$param,'fetch-raw',$server,$extra,$DBH);
unset($param);

// fetch all the questions
while($fetchQuestions = $getQuestions->fetch())

    {

        // save into array and generate the column questions
        $questions[] = $fetchQuestions["ansr_question"];
        $question_headers .= '<td height="19" nowrap style="background-color:#e9e9e9; font-weight:400;">'.trim(ucfirst($fetchQuestions["ansr_question"])).'</td>';

    }

// loop array
$num_questions = count($questions);
$num_questions_check = $num_questions -1;
for($i=0; $num_questions > $i; ++$i)

    {

    // prepare PDO params
    $param[] = $questions[$i];

    // use the count to perform if statement when last question has been reached
    $comma = ',';
    if($num_questions_check == $i)

        {
        $comma = '';
        }

    // generate the 2 dynamic parts of the query
    $sql_part1 .= "max(qq.question$i) as 'answer$i',";
    $sql_part2 .= "case when q.ansr_question = ? then ansr_answer else null end as question$i$comma ";

    }


// make it 1 query
$query = "select 
$sql_part1
ansr_recordid, 
ansr_type
FROM (
    SELECT
        ansr_recordid, 
        ansr_type,
        $sql_part2
    FROM(
        select 
            ansr_recordid, 
            ansr_question,
            ansr_answer,
            ansr_type,
            ansr_sortorder
            from forms_123456 where is_answer=1 order by ansr_recordid, ansr_sortorder 
            ) q
    )qq
GROUP BY ansr_recordid";

// lets try it!
$getAnswers = processQuery($query,$param,'fetch-raw',$server,$extra,$DBH);
unset($param);


// show questions and other data
echo '<td height="19" nowrap style="background-color:#e9e9e9; font-weight:600;">Status</td>
    <td height="19" nowrap style="background-color:#e9e9e9; font-weight:600;">Details</td>';

echo $question_headers;

echo '<td height="19" nowrap style="background-color:#e9e9e9; font-weight:600;">Record ID</td>
    <td height="19" nowrap style="background-color:#e9e9e9; font-weight:600;">Start Date</td>
    <td height="19" nowrap style="background-color:#e9e9e9; font-weight:600;">End Date</td>
</tr>';


// show values ----------------------------------------
$first = 1;
while($fetch = $getAnswers->fetch())

{

// change color per row
if($first == 0)

    {
    $first = 1;
    $bgcolor = '#f1f1f1';
    }
else
    {
    $first = 0;
    $bgcolor = '';
    }

echo '<tr>';

echo '<td height="19" nowrap style="background-color:'.$bgcolor.'; font-weight:400;">OK</td>
    <td height="19" nowrap style="background-color:'.$bgcolor.'; font-weight:400;">Bekijken</td>';

// loop the number of questions so we get the same amount of columns
for($i=0; $num_questions > $i; ++$i)

    {
    echo '<td height="19" nowrap style="background-color:'.$bgcolor.'; font-weight:400;">'.trim(ucfirst($fetch["answer$i"])).'</td>';
    }

echo '<td height="19" nowrap style="background-color:'.$bgcolor.'; font-weight:400;">'.$fetch["ansr_recordid"].'</td>
    <td height="19" nowrap style="background-color:'.$bgcolor.'; font-weight:400;">Start Date</td>
    <td height="19" nowrap style="background-color:'.$bgcolor.'; font-weight:400;">End Date</td>';

echo '</tr>';

}

?>

</table>
</div>

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-08-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-04-08
    相关资源
    最近更新 更多