我正在开发一个内容管理系统,我想听听你对以下内容的看法:
我有一张桌子page
。我们假设它看起来像这样
ID | Title | Content
1 | Test | This is a test
除此之外,我有一个page_option
表(所以我可以存储与页面相关的选项,但我不希望有一个有限的选项列表 - 模块可以添加自己的选项到一个页面,如果需要。)
page_option
表可能如下所示:
page_id | option_key | option_value
1 | background | red
1 | module1_key | chicken
现在要检索页面对象,我使用Active Record类执行以下操作(这是针对此问题的伪编码):
function get_by_id($page_id) {
$this->db->where('id', $page_id);
$page_object = $this->db->get('page');
if($page_object->num_rows() > 0) {
$page = $page_object->row();
$this->db->where('page_id', $page_id);
$options_object = $this->db->get('option');
if($options_object->num_rows() > 0) {
$page->options = $options_object->result();
}
return $page;
}
return $page_object->row();
}
我想知道的是,有没有办法在一个查询中执行此操作,以便选项键成为我的选择中的虚拟列,所以我得到:
ID | Title | Content | background | module1_key
1 | Test | This is a test | red | chicken
在我的结果中,而不是对每一行进行单独的查询。如果有10,000个怎么办?等
非常感谢提前!
答案 0 :(得分:1)
使用EAV(Entity-Attribute-Value)模型,您将始终不得不应对这些问题。由于查询的复杂性,它们的效率也不高(大多数都需要旋转)。
SELECT page_id,
MAX(CASE WHEN option_key = 'background' THEN option_value END) background,
MAX(CASE WHEN option_key = 'module1_key' THEN option_value END) module1_key,
MAX(CASE WHEN option_key = 'module2_key' THEN option_value END) module2_key
FROM page_option
GROUP BY page_id
例如,给定此表:
| PAGE_ID | OPTION_KEY | OPTION_VALUE |
|---------|-------------|--------------|
| 1 | background | red |
| 1 | module1_key | chicken |
| 2 | module1_key | duck |
| 3 | module1_key | cow |
| 4 | background | blue |
| 4 | module2_key | alien |
| 4 | module1_key | chicken |
您将获得以下输出:
| PAGE_ID | BACKGROUND | MODULE1_KEY | MODULE2_KEY |
|---------|------------|-------------|-------------|
| 1 | red | chicken | (null) |
| 2 | (null) | duck | (null) |
| 3 | (null) | cow | (null) |
| 4 | blue | chicken | alien |
小提琴here。
然后加入page
表就是这样:)我省略了那个部分,以便将查询集中在分组本身。
答案 1 :(得分:0)
如果您可以使用activerecord类添加虚拟字段,则可以执行类似的操作:
$this->db->add_field("(select group_concat(concat(option_key,':',option_value) SEPARATOR ' ') from page_option where page_id=$page_id group by page_id)");
它不会是最佳的......
答案 2 :(得分:0)
如果option_key
每page_id
个background
(您没有两个或更多page_id==1
SELECT page.page_id, page.title, page.content,
GROUP_CONCAT(option_key SEPARATOR '@') AS option_keys,
GROUP_CONCAT(option_value SEPARATOR '@') as option_values,
FROM page
LEFT JOIN page_option ON page_option.page_id=page.page_id
WHERE page.page_id=USER_SPECIFIED_ID
),您可以这样做:
$result
您可以执行此SQL查询并将其结果放入$result
。应该完成$result[$i]["options"] = array_combine(
explode("@",$result[$i]["option_keys"]),
explode("@",$result[$i]["option_values"])
);
的每个项目后
foreach
您可以使用array_walk
执行此操作,也可以使用$result[$i]["options"]
。
在这些之后你有一个关联数组,其中包含{
"background" => "red",
"module_key1"=> "chicken"
}
中的选项:
{{1}}
我希望这是你想要的。