查询此问题的最佳方法是什么?

时间:2011-07-11 07:18:49

标签: php mysql

我的表格看起来像这样:

questions:
id description
1   Q1
2   Q2

answers:
id question_id x y description
1     1        1 2   A1
2     1        3 4   A2
3     2        5 6   A3
4     2        7 8   A4

我想要的是一个可以输出的查询:

Q1 A1 1,2 A2 3,4
Q2 A3 5,6 A4 7,8

我一直在拉我的头发好几天试图解决这个问题。我在PHP和MySQL中这样做,所以如果有人能在那里发光,那真的很棒。

编辑:我忘了提到我也在使用CodeIgniter。所以,这可能有助于解答。

3 个答案:

答案 0 :(得分:2)

考虑到每个问题可能存在随机数量的答案,您无法设计将返回固定数量列的查询。您必须为每个问题返回一个结果,然后在代码中进行一些解析。

GROUP_CONCAT函数可能对此类问题有所帮助:

SELECT q.description, GROUP_CONCAT(
    CONCAT(a.description,' ',a.x,',',a.y) ORDER BY a.id
    SEPARATOR ' '
    ) AS answers
FROM questions q
  JOIN answers a ON a.question_id = q.id
GROUP BY q.description;

将返回

+-------------+---------------+
| description | answers       |
+-------------+---------------+
| Q1          | A1 1,2 A2 3,4 |
| Q2          | A3 5,6 A4 7,8 |
+-------------+---------------+
2 rows in set (0.00 sec)

您可以通过在代码中解析结果的任何内容来更改SEPARATOR值。您可以使用ORDER BY函数的GROUP_CONCAT子句在每个答案的返回结果中排序答案(此处我按答案ID排序)。

修改:如果您确定每个问题的答案永远不会超过4个,您可以发出以下查询,将每个答案放在自己的列中:

SELECT description,
  REPLACE(SUBSTRING(SUBSTRING_INDEX(answers, '$', 1), LENGTH(SUBSTRING_INDEX(answers, '$', 1 - 1)) + 1), '$', '') answer_1,
  REPLACE(SUBSTRING(SUBSTRING_INDEX(answers, '$', 2), LENGTH(SUBSTRING_INDEX(answers, '$', 2 - 1)) + 1), '$', '') answer_2,
  REPLACE(SUBSTRING(SUBSTRING_INDEX(answers, '$', 3), LENGTH(SUBSTRING_INDEX(answers, '$', 3 - 1)) + 1), '$', '') answer_3,
  REPLACE(SUBSTRING(SUBSTRING_INDEX(answers, '$', 4), LENGTH(SUBSTRING_INDEX(answers, '$', 4 - 1)) + 1), '$', '') answer_4
FROM (
    SELECT q.description, GROUP_CONCAT(
        CONCAT(a.description,' ',a.x,',',a.y) ORDER BY a.id
        SEPARATOR '$'
        ) AS answers
    FROM questions q
      JOIN answers a ON a.question_id = q.id
    GROUP BY q.description
  ) t;

将返回

+-------------+----------+----------+----------+----------+
| description | answer_1 | answer_2 | answer_3 | answer_4 |
+-------------+----------+----------+----------+----------+
| Q1          | A1 1,2   | A2 3,4   |          |          |
| Q2          | A3 5,6   | A4 7,8   | A5 9,10  |          |
+-------------+----------+----------+----------+----------+
2 rows in set (0.00 sec)

我为第二个问题添加了答案。

答案 1 :(得分:1)

select * from answers ORDER BY question_id

$question_id = 0;
$print_ln = null;
foreach ($result as $row) {
  if ($question_id != $row['question_id']) { 
     echo "<br>";
     $question_id = $row['question_id'];
     $print_ln = "Q" . $row['question_id'] . " " . $row['description'] . " " . $row['x'] . "," . $row['y'];
  } else { 
     $print_ln = $print_ln . " " . $row['description'] . " " . $row['x'] . "," . $row['y'];
  }
  echo $print_ln;
 }

请注意,此代码仍需要一些工作......它可以让您了解如何执行此操作。

答案 2 :(得分:0)

此查询:

SELECT 
      q.id
    , q.description
    , a.description
    , CONCAT(a.x, ',', a.y)
FROM questions AS q
    JOIN answers AS a
        ON a.question_id = q.id
ORDER BY q.id
       , a.id

将显示:

| 1 | Q1 | A1 | 1,2 |
| 1 | Q1 | A2 | 3,4 |
| 2 | Q2 | A3 | 5,6 |
| 2 | Q2 | A4 | 7,8 |

您所描述的最终结果称为旋转,在MySQL中并不容易,取决于您拥有的数据。例如,对于一个问题,应该显示什么,有两个以上的答案?

为什么结果如此:

| Q1 | A1 | 1,2 | A2 | 3,4 | 
| Q2 | A3 | 5,6 | A4 | 7,8 |

而不是那样?:

| Q1 | A1 | 1,2 | A2 | 3,4 | 
| Q2 | A4 | 7,8 | A3 | 5,6 | 

无论如何,每个问题最多4个答案并按answers.id排序,这将有效。尽管使用上一个查询并在PHP中进行透视可能是最好的,您可以在这里处理可变数量的列而没有问题:

SELECT 
      q.id
    , q.description
    , ( SELECT a.description
        FROM answers AS a
        WHERE a.question_id = q.id
        ORDER BY a.id  LIMIT 0,1
      ) AS answer1
    , ( SELECT CONCAT(a.x, ',', a.y)
        FROM answers AS a
        WHERE a.question_id = q.id
        ORDER BY a.id  LIMIT 0,1
      ) AS xy1
    , ( SELECT a.description
        FROM answers AS a
        WHERE a.question_id = q.id
        ORDER BY a.id  LIMIT 1,1
      ) AS answer2
    , ( SELECT CONCAT(a.x, ',', a.y)
        FROM answers AS a
        WHERE a.question_id = q.id
        ORDER BY a.id  LIMIT 1,1
      ) AS xy2
    , ( SELECT a.description
        FROM answers AS a
        WHERE a.question_id = q.id
        ORDER BY a.id  LIMIT 2,1
      ) AS answer3
    , ( SELECT CONCAT(a.x, ',', a.y)
        FROM answers AS a
        WHERE a.question_id = q.id
        ORDER BY a.id  LIMIT 2,1
      ) AS xy3
    , ( SELECT a.description
        FROM answers AS a
        WHERE a.question_id = q.id
        ORDER BY a.id  LIMIT 3,1
      ) AS answer4
    , ( SELECT CONCAT(a.x, ',', a.y)
        FROM answers AS a
        WHERE a.question_id = q.id
        ORDER BY a.id  LIMIT 3,1
      ) AS xy4
FROM questions AS q
ORDER BY q.id