连接codeigniter中多个表的数据

时间:2014-03-25 17:45:45

标签: php mysql codeigniter

你们如何从两个或多个表中获取数据并在codeigniter中操作它?

假设我们有2个表格的问题和答案。一个问题可以有一个或多个答案。现在让我们假设一个答案可以有喜欢和不喜欢。你们如何得到所有问题的答案,以便在视图中显示它们?我会告诉你我的解决方案,但我很好奇你的。

我使用像这样的库:

class Questions_library {
    var $CI = &get_instance();

    function get_questions_with_answers(){    
        $data = array();
        $questions = $this->CI->questions_model->get_questions(); 

        if ($questions):
            foreach ($questions as $q): 
                $temp = array();
                $temp = $q;
                $temp['answers'] = $this->CI->answerslibrary->get_answers($q['id']);
                $data[] = $temp;         
            endforeach;    
        endif; 

        return $data ? $data : false;
    }
}

现在在答案库中,我可以采取相同的方法来得到答案,并回答和不喜欢。

我的方法中的一个缺点是,如果我想用分数或喜欢/不喜欢等分类来显示我的问题,我必须在我的模型中使用连接或嵌套查询,并且我可以利用我的图书馆。

您如何管理此任务?

1 个答案:

答案 0 :(得分:2)

正如@nevermind指出的那样,唯一的方法是在SQL中使用JOIN。你所做的任何PHP循环数据都将成为PHP和MySQL的瓶颈。使用JOIN的唯一查询,您将获得所有结果,(使用GROUP BY子句与SUMCOUNT获取元素的数量)和您将能够使用ORDER BY。并且您只对DDBB使用查询,而使用您的方法,您使用大量查询(每行1个)来获得相同的结果。相信我,我已经看到了你在上面提出的系统中的代码,它就像一件紧身衣。

如果您想获得有关使用MySQL子句的更多帮助,请发布您的代码,我会指出如何操作。

更新

让我们尝试一下SQLFiddle:

起点:两个表,问答,具有以下结构:

CREATE TABLE IF NOT EXISTS `answer` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `question_id` int(11) DEFAULT NULL,
  `title` tinytext COLLATE utf8_spanish_ci,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=9 DEFAULT CHARSET=utf8 COLLATE=utf8_spanish_ci;

INSERT INTO `answer` (`id`, `question_id`, `title`) VALUES
    (1, 1, 'a1'),
    (2, 1, 'a2'),
    (3, 1, 'a3'),
    (4, 1, 'a4'),
    (5, 1, 'a5'),
    (6, 2, 'a3'),
    (7, 2, 'a2'),
    (8, 2, 'a1');    

CREATE TABLE IF NOT EXISTS `question` (
  `id` int(11) DEFAULT NULL,
  `title` tinytext COLLATE utf8_spanish_ci,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_spanish_ci;

INSERT INTO `question` (`id`, `title`) VALUES
    (1, 'question 1'),
    (2, 'question 2');

http://sqlfiddle.com/#!2/400994/6

如您所见,在小提琴中,我们得到INNER JOIN的正确数据,与两个表的JOIN一样多。

使用GROUP BYLIMIT,我们可以获得所有值,无需担心:

SELECT 
  q.id qId
, q.title qTitle
, GROUP_CONCAT( a.id SEPARATOR " ")

FROM question q

INNER JOIN answer a 
ON a.question_id = q.id

GROUP BY qId 
LIMIT 3

http://sqlfiddle.com/#!2/400994/8

上面的查询将连接表,对值进行分组,然后,然后,限制结果行的数量。如你所见,你得到所有的价值,你甚至可以计算价值,求和,连接它们......尽可能多的:

SELECT 
  q.id qId
, q.title qTitle
, GROUP_CONCAT( a.id SEPARATOR " ")
, SUM( a.id )
, COUNT( a.id )
FROM question q

INNER JOIN answer a 
ON a.question_id = q.id

GROUP BY qId 
LIMIT 3

http://sqlfiddle.com/#!2/400994/11

当然,您可能希望通过答案数量,ASC或DESC来命令它们:

SELECT 
  q.id qId
, q.title qTitle
, GROUP_CONCAT( a.id SEPARATOR " ")
, SUM( a.id ) sumIdsValues
, COUNT( a.id ) totalAnswers
FROM question q

INNER JOIN answer a 
ON a.question_id = q.id

GROUP BY qId 
ORDER BY totalAnswers ASC
LIMIT 3

http://sqlfiddle.com/#!2/400994/12

其他的是获取不同答案的值,以创建要导出的数组。在这种情况下,您可以使用CONCAT

复合值中的JSON
SELECT 
  q.id qId
, q.title qTitle
, CONCAT( "[", GROUP_CONCAT( a.id SEPARATOR ", "), "]" ) idArrays
, SUM( a.id )
, COUNT( a.id )
FROM question q

INNER JOIN answer a 
ON a.question_id = q.id

GROUP BY qId 
LIMIT 3

http://sqlfiddle.com/#!2/400994/14

然后您将字段idArrays = [1, 2, 3, 4, 5]作为JSON数组,您可以使用json_decode()进行解码并分配给var。你可能会使用更复杂的结构,重要的是知道你想要复合什么,然后用CONCAT编写MySQL子句来复合它,XD