我想将以下内容编写为 MySQL SELECT 语句,以减少获取信息所需的查询数量,但我不知道如何编写它。
我有两个表——tags 和 books_tags(多对多关系联结表)。我想要的最终输出将打印如下:
<label for="formFiltertag1"><input type="checkbox" name="tag[]" value="1" id="formFiltertag1" class="rank90" /> PHP (15)<br /></label>
其中文本是标签的名称 (tags.name),括号中的数字是标签 ID 在联结表中出现的次数 (COUNT(books_tags.tag_id))。 输入 ID 和值将根据tags.id 字段动态变化。
我最初以为我只是运行一个查询来从标签表中获取所有信息,然后使用 foreach 循环为每个标签运行单独的计数查询,但随着标签数量的增长,这可能会很快变得难以处理。
这是我现在编写的一个示例(使用 CodeIgniter 的 ActiveRecord 模式)...
型号:
function get_form_tags() {
$query = $this->db->get('tags');
$result = $query->result_array();
$tags = array();
foreach ($result as $row) {
$this->db->select('tag_id')->from('books_tags')->where('tag_id', $row['id']);
$subResult = $this->db->count_all_results();
$tags[] = array('id' => $row['id'], 'tag' => $row['tag'], 'count' => $subResult);
}
return $tags;
}
控制器:
function index() {
$this->load->model('browse_model', 'browse');
$tags = $this->browse->get_form_tags();
$data['content'] = 'browse/browse';
$data['tags'] = $tags;
$this->load->view('global/template', $data);
}
视图(浓缩):
<?php foreach ($tags as $tag) : ?>
<label for="formFiltertag<?php echo $tag['id'] ?>"><input type="checkbox" name="tag[]" value="<?php echo $tag['id'] ?>" id="formFiltertag<?php echo $tag['id'] ?>" class="rank<?php echo $tag['count'] ?>" /> <?php echo $tag['tag'] . ' (' . $tag['count'] . ')' ?><br /></label>
<?php endforeach; ?>
这可行,但就像我说过的,它将创建比完成工作所需的更多的查询。当然有更好的方法。佩妮有什么想法吗?
非常感谢, 马库斯
select t, coalesce(btc.Count, 0) as Count
from tags t
left outer join (
select tagid, count(*) as Count
from books_tags
group by tagid
) btc on t.tagid = btc.tagid
$result
返回一个数组数组,其中 array_combine()
需要一个字符串数组。
因为这个任务可以通过一次数据库访问来完成,所以它应该如此。 使用 LEFT JOIN 启用每个标签记录的每个 book_tags 记录的计数。
public function getFormTags(): array
{
return $this->db
->select('tags.id, tags.tag, COUNT(books_tags.tag_id) count')
->join('books_tags', 'books_tags.tag_id = tags.id', 'LEFT')
->group_by('tags.id')
->get('tags')
->result_array();
}
渲染的 SQL(引用将因 SQL 方言而异):
SELECT `tags`.`id`, `tags`.`tag`, COUNT(books_tags.tag_id) count
FROM `tags`
LEFT JOIN `books_tags` ON `books_tags`.`tag_id` = `tags`.`id`
GROUP BY `tags`.`id`