簡體   English   中英

Laravel 數據庫查詢 WHERE 日期大於不使用 JOIN

[英]Laravel DB Query WHERE date greater than not working with JOIN

背景

我已經編寫了一個 SQL 查詢,它非常適合我的需求,我正在嘗試將它添加到 Laravel 中的排隊作業中。 我不想使用 Eloquent 模型,而是想使用帶有 DB Query 的 go 來確保更好的性能,因為最終會有很多連接和條件。 我在檢查日期時遇到了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 個結果,這是我當前數據所預期的。

created_at 上次閱讀
2021-03-26 19:02:53 2021-03-23 19:31:30
2021-03-26 19:02:58 2021-03-23 19:31:30

這就是我在 Laravel 中的寫法:

$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 中運行它會返回准確的結果。

語境

對於上下文,這是我正在使用的數據結構和一些數據。

參與者

ID 線程 ID 用戶身份 上次閱讀 created_at 更新時間 刪除_at 最后通知
9 8 178 2021-03-23 23:31:53 2021-03-23 22:16:48 2021-03-23 23:31:53 NULL NULL

消息

ID 線程 ID 用戶身份 身體 created_at 更新時間 刪除_at
159 3 177 阿法德 2021-03-26 19:02:53 2021-03-26 19:02:53 NULL
160 3 177 爸爸 2021-03-26 19:02:58 2021-03-26 19:02:58 NULL

問題

似乎數據庫查詢代碼導致名稱相似的列混淆。 兩個表都有一個名為created_at的列,但我只需要messages表中的該列。 我的SELECT只要求該列,指定正確的表。 但是這個數據庫查詢連接中的某些東西導致它混淆了。

使用不同的連接並刪除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期間混淆了。 但我不知道如何澄清這一點。 我曾嘗試尋找其他有此問題的人,但似乎找不到任何相關內容。

已經試過了

我已經嘗試了一些結果沒有改變的東西。

  • 改變命令的順序——比如將select()移到語句的開頭,就像這樣。
  • 使用whereDate而不是where (注意 - 為了性能,我寧願避免這種情況,但想以防萬一)。
  • 使用joinjoinLeftjoinRight
  • on子句中使用where而不是兩個on s。 像這樣
    ->leftJoin('participants', function ($join) { $join->on('messages.thread_id', '=', 'participants.thread_id') ->where('messages.user_id', ',='. 'participants;user_id'); })

有人對我可以嘗試的事情有任何指導嗎? 應該是一個如此簡單的任務,並且已經變成了試圖理解為什么它在 SQL 而不是 Laravel 的 DB Query Builder 中工作的幾個小時。

查詢生成器的where function 將始終假定右側是一個值,並將在准備好的語句中將其用作文字(在本例中為字符串)。 如果要比較列,則需要使用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 子句

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM