当前位置: 首页 > 知识库问答 >
问题:

Laravel DB查询,其中日期大于不使用联接

淳于俊迈
2023-03-14

我已经编写了一个非常适合我需要的SQL查询,我正在尝试将它添加到Laravel中的一个排队作业中。我没有使用雄辩的模型,而是希望使用DB查询来确保更好的性能,因为最终会有许多连接和条件。在检查日期时,where子句有问题,但它在SQL中运行时工作得非常好。我删除了该查询的其他部分,仅包括调试此问题所必需的内容。

原始SQL:

SELECT `messages`.`created_at`, `participants`.`last_read`
FROM `messages` 
LEFT JOIN `participants` ON `messages`.`thread_id` = `participants`.`thread_id` AND `messages`.`user_id` != `participants`.`user_id` 
WHERE `messages`.`created_at` > `participants`.`last_read`;

当我直接在SQL中运行这个时,我看到2个结果,这与我当前的数据是意料之中的。

我在拉拉维尔是这样写的:

$query = DB::table('messages')
    ->leftJoin('participants', function ($join) {
        $join->on('messages.thread_id', '=', 'participants.thread_id')
            ->on('messages.user_id', '!=', 'participants.user_id');
    })
    ->select('messages.created_at as message_date', 'participants.last_read as last_read')
    ->where('messages.created_at', '>', 'participants.last_read');

当我执行此操作时,结果为空。我从DB Query builder转储了最终的SQL,以确保它是正确的,它是这样的:

select `messages`.`created_at` as `message_date`, `participants`.`last_read` as `last_read`
from `messages`
left join `participants`
on `messages`.`thread_id` = `participants`.`thread_id` and `messages`.`user_id` != `participants`.`user_id`
where `messages`.`created_at` > participants.last_read

并且直接在SQL中运行它将返回准确的结果。

对于上下文,这里是数据结构和我正在使用的一些数据。

与会者

消息

DB查询代码似乎导致了具有相似名称的列被混在一起。这两个表都有一个名为created_at的列,但我只需要messages表中的该列。我的select只请求该列,指定正确的表。但是这个DB查询连接中的某些东西导致了它的混淆。

使用不同的联接,并删除where子句,我意识到日期并不总是正确的。例如,下面是我使用leftjoin时的结果

{
  "message_date": "2021-03-23 00:30:42",
  "last_read": "2021-03-26 00:22:48"
},
{
  "message_date": "2021-03-23 00:31:25",
  "last_read": "2021-03-26 00:22:48"
}

注意,message_datelast_read值与直接运行SQL时的值相反。所以这一定是问题所在。

我更改为RightJoin,结果是反向的:

{
    "message_date": "2021-03-26 19:02:53",
    "last_read": "2021-03-23 19:31:30",
},
{
    "message_date": "2021-03-26 19:02:58",
    "last_read": "2021-03-23 19:31:30",
}

那应该管用,对吧?我重新添加where子句,但结果仍然是空的。

我想我需要做一些事情来告诉查询生成器正确处理这些列,因为它们似乎在whereselect过程中被混淆了。但我不知道该怎么澄清。我试着寻找与此问题相关的其他人,但我似乎找不到任何相关的东西。

我已经尝试了几件事情,结果都没有变化。

  • Changing the order of the commands - like moving the select() to the beginning of the statement, things like this.
  • Using whereDate instead of where. (Note - for performance I'd rather avoid this, but wanted to try just in case).
  • Using join, joinLeft, and joinRight.
  • Using where in the on clause instead of two ons. Like this
    ->leftJoin('participants', function ($join) {
        $join->on('messages.thread_id', '=', 'participants.thread_id')
            ->where('messages.user_id', '!=', 'participants.user_id');
    })
    

    有人对我可以尝试的事情有什么指导吗?这应该是一个如此简单的任务,并且已经变成了数小时的努力来理解为什么它在SQL中工作,而不是在Laravel的DB查询构建器中工作。

共有1个答案

融宏伟
2023-03-14

查询生成器的where函数将始终假定右侧是一个值,并将其作为文字(在本例中为字符串)在准备好的语句中使用。如果要比较列,则需要使用whereColumn:

$query = DB::table('messages')
    ->leftJoin('participants', function ($join) {
        $join->on('messages.thread_id', '=', 'participants.thread_id')
            ->on('messages.user_id', '!=', 'participants.user_id');
    })
    ->select('messages.created_at as message_date', 'participants.last_read as last_read')
    ->whereColumn('messages.created_at', '>', 'participants.last_read')->get();

单据中可以找到其他where条款

 类似资料:
  • 我想在hibernate中选择最大日期,但出现以下错误: Java语言sql。SqlSyntaxerRorexException:ORA-00932:不一致的数据类型:预期的时间戳得到的数字 查询是: 数据库是oracle。数据库中该字段的类型为时间戳(6)

  • 我有两个约会。 我如何检查一个日期是否比另一个日期大? 我试过这个: 但它不起作用=( 这种dd/mm/yyyy格式有方法吗?

  • 如何使用BETWEEN运算符选择存储为varchar(格式:“2012.04”)的日期? 我需要在此字段上选择一年间隔。 现在我正在尝试,但这会导致我的MySQL语法错误: 日期现在是静态的(用于测试),但我需要计算BETWEEN中的第二个值,以便它与BETWEEN部分的第一个值精确为-1年。 非常感谢你!!

  • 然而,这并不奏效。 为什么有人能提供一个参考吗?

  • 我有一个和列在我的表中。所以我试图检查指定的日期是否在这两列的范围内。例如: from_date: 2021-08-26 to_date: 2021-08-29 date: 2021-08-27 我试图使用运算符,但是语法是从相同的列名中选择日期范围。 在我的例子中,我想从不同的列中选择日期范围,比如下面的查询示例。有没有办法做到这一点? 谢谢你!

  • 本文向大家介绍使用INTERVAL添加天数后,MySQL查询获取的日期记录大于当前日期?,包括了使用INTERVAL添加天数后,MySQL查询获取的日期记录大于当前日期?的使用技巧和注意事项,需要的朋友参考一下 让我们首先创建一个表- 使用插入命令在表中插入一些记录- 使用select语句显示表中的所有记录- 这将产生以下输出- 这是从AddDay列添加天后获取大于当前日期的数据记录的查询- 这将