使用 CodeIgniter 查询构建器方法对第一个表中的每条记录选择第二个表中的记录

发布于 2024-09-25 07:00:09 字数 1810 浏览 3 评论 0原文

我想将以下内容编写为 MySQL SELECT 语句,以减少获取信息所需的查询数量,但我不确定如何编写它。

我有两个表 - 标签和 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; ?>

这可行,但就像我所说的,它将创建比获取所需更多的查询工作完成了。当然有更好的方法。

I'd like to write the following as a MySQL SELECT statement to cut down on the number of queries required to get the information, but I'm not sure how to write it.

I have two tables - tags and books_tags (a many-to-many relationship junction table). The final output I want would print as follows:

<label for="formFiltertag1"><input type="checkbox" name="tag[]" value="1" id="formFiltertag1" class="rank90" /> PHP (15)<br /></label>

Where the text is the name of the tag (tags.name) and the number in parens is the count of how often the tag's ID appears in the junction table (COUNT(books_tags.tag_id)). The input ID and value will be dynamic based on the tags.id field.

I originally thought I'd just run a query that gets all of the info from the tag table and then use a foreach loop to run a separate count query for each one, but as they number of tags grows that could get unwieldy quickly.

Here's an example as I have it written now (using CodeIgniter's ActiveRecord pattern)...

The Model:

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;
}

The controller:

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);
}

The view (condensed):

<?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; ?>

This works, but like I've said it's going to create way more queries than needed to get the job done. Surely there's a better way.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

疯狂的代价 2024-10-02 07:00:10
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
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
挽梦忆笙歌 2024-10-02 07:00:10

$result 返回一个数组数组,其中 array_combine() 需要一个字符串数组。

$result returns an array of arrays, where array_combine() expects an array of strings.

雅心素梦 2024-10-02 07:00:10

因为这个任务可以通过一次数据库访问来完成,所以它应该如此。使用 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`

Because this task can be accomplished with a single trip to the database, it should. Use a LEFT JOIN to enable the counting of each book_tags record per tags record.

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();
}

Rendered SQL (quoting will vary by SQL dialect):

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`
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文