【问题标题】:convert SQL query to query builder style将 SQL 查询转换为查询生成器样式
【发布时间】:2015-12-08 19:41:39
【问题描述】:

我试图了解如何将 SQL 查询转换为 laravel 中的查询构建器样式。

我的 SQL 查询是:

$tagid = Db::select("SELECT `id` FROM `wouter_blog_tags` WHERE `slug` = '".$this->param('slug')."'");

$blog = Db::select("SELECT * 
            FROM `wouter_blog_posts` 
            WHERE `published` IS NOT NULL 
            AND `published` = '1'
            AND `published_at` IS NOT NULL 
            AND `published_at` < NOW()
            AND (

            SELECT count( * ) 
            FROM `wouter_blog_tags` 
            INNER JOIN `wouter_blog_posts_tags` ON `wouter_blog_tags`.`id` = `wouter_blog_posts_tags`.`tags_id` 
            WHERE `wouter_blog_posts_tags`.`post_id` = `wouter_blog_posts`.`id` 
            AND `id` 
            IN (
             '".$tagid[0]->id."'
            )) >=1
            ORDER BY `published_at` DESC 
            LIMIT 10 
            OFFSET 0");

我现在最终转换为查询生成器的地方是:

   $test = Db::table('wouter_blog_posts')
->where('published', '=', 1)
->where('published', '=', 'IS NOT NULL')
->where('published_at', '=', 'IS NOT NULL')
->where('published_at', '<', 'NOW()')
  ->select(Db::raw('count(*) wouter_blog_tags'))
->join('wouter_blog_posts_tags', function($join)
{ 
$join->on('wouter_blog_tags.id', '=', 'wouter_blog_posts_tags.tags_id')
->on('wouter_blog_posts_tags.post_id', '=', 'wouter_blog_posts.id')
->whereIn('id', $tagid[0]->id);
})
->get();

我读到我不能在连接中使用 whereIn。我现在得到的错误:

调用未定义的方法 Illuminate\Database\Query\JoinClause::whereIn()

我真的不知道如何将我的 SQL 转换为查询生成器。我希望当我看到我的查询的良好工作转换时,我能理解下一次我必须如何做。

【问题讨论】:

  • 我没试过这个,但也许用-&gt;whereRaw('id IN ?', [$tagid[0]-&gt;id])。只需确保最后的 bindings 参数是一个数组。但是,我不知道您为什么将 WHERE IN 用于一个值 - $tagid[0]-&gt;id。这会返回一个数组还是什么?这是一个替代解决方案stackoverflow.com/questions/26913776/…

标签: php mysql laravel octobercms


【解决方案1】:

这对我有用:

DB::table('wouter_blog_posts') ->whereNotNull('已发布') ->where('已发布', 1) ->whereNotNull('published_at') ->whereRaw('published_at whereRaw("(选择计数(*) 来自wouter_blog_tags 内连接wouter_blog_posts_tags ON wouter_blog_tags.id = wouter_blog_posts_tags.tags_id 在哪里wouter_blog_posts_tags.post_id = wouter_blog_posts.idid 在 ( '".$tagid."' )) >=1") ->orderBy('published_at', 'desc') ->跳过(0) ->采取(10) ->分页($this->property('postsPerPage'));

【讨论】:

    【解决方案2】:

    以下查询构建器代码将为您提供您在DB::select 中的确切 SQL 查询:

    DB::table('wouter_blog_posts')
        ->whereNotNull('published')
        ->where('published', 1)
        ->whereNotNull('published_at')
        ->whereRaw('`published_at` < NOW()')
        ->where(DB::raw('1'), '<=', function ($query) use ($tagid) {
            $query->from('wouter_blog_tags')
                ->select('count(*)')
                ->join('wouter_blog_posts_tags', 'wouter_blog_tags.id', '=', 'wouter_blog_posts_tags.tags_id')
                ->whereRaw('`wouter_blog_posts_tags`.`post_id` = `wouter_blog_posts`.`id`')
                ->whereIn('id', [$tagid[0]->id]);
        })
        ->orderBy('published_at', 'desc')
        ->skip(0)
        ->take(10)
        ->get();
    

    必须反转子查询条件,因为您不能将子查询作为where 方法的第一个参数并且仍然能够绑定条件值。所以它是1 &lt;= (subquery),相当于(subquery) &gt;= 1。上述代码生成的查询将如下所示:

    SELECT * 
    FROM `wouter_blog_posts` 
    WHERE `published` IS NOT NULL 
           AND `published` = 1 
           AND `published_at` IS NOT NULL 
           AND `published_at` < Now() 
           AND 1 <= (SELECT `count(*)` 
                     FROM `wouter_blog_tags` 
                          INNER JOIN `wouter_blog_posts_tags` 
                                  ON `wouter_blog_tags`.`id` = 
                                     `wouter_blog_posts_tags`.`tags_id` 
                     WHERE `wouter_blog_posts_tags`.`post_id` = 
                           `wouter_blog_posts`.`id` 
                            AND `id` IN ( ? )) 
    ORDER  BY `published_at` DESC 
    LIMIT  10 offset 0 
    

    在创建更复杂的查询时,我的过程是首先创建它们并在 SQL 环境中试用它们,以确保它们按预期工作。然后我使用查询生成器逐步实现它们,但不是在查询末尾使用get(),而是使用toSql(),它将为我提供查询生成器生成的查询的字符串表示,允许我将它与我的原始查询进行比较,以确保它是相同的。

    【讨论】:

    • 查询生成器的工作方式与我预期的完全不同。我不明白:->'1','id)。没有列 1 我得到的错误:语法错误,意外的 ''1'' (T_CONSTANT_ENCAPSED_STRING),期望标识符 (T_STRING) 或变量 (T_VARIABLE) 或 '{' 或 '$'
    • 那是我的错误,我没有注意到因为我颠倒了条件,where 方法的第一个参数被引用,因为它期望在那里有一列。我已经更新了我的答案以使用 DB::raw 来解决这个问题。
    猜你喜欢
    • 2021-08-07
    • 2023-01-20
    • 2019-06-21
    • 1970-01-01
    • 2019-10-14
    • 2015-12-13
    • 1970-01-01
    • 2017-06-01
    • 2019-09-08
    相关资源
    最近更新 更多