简体   繁体   English

Laravel子查询问题,使用whereIn时获取最新行

[英]Laravel SubQuery Question, Get the most recent row when using whereIn

I have two tables: 我有两个表:

Threads 主题

id, created_at, updated_at, deleted_at

Messages 消息

id, thread_id, user_id, created_at, updated_at, deleted_at

Here is a link to an SQL Fiddle I have created which builds this relationship: 这是我创建的建立此关系的SQL Fiddle的链接:

http://sqlfiddle.com/#!9/915829/3/0 http://sqlfiddle.com/#!9/915829/3/0

Thread Model has this relationship for messages 线程模型对消息具有这种关系

 /**
 * Messages relationship.
 *
 * @return \Illuminate\Database\Eloquent\Relations\HasMany
 *
 * @codeCoverageIgnore
 */
public function messages()
{
    return $this->hasMany(Message::class, 'thread_id', 'id');
}

Message Model has this relationship for Thread: 消息模型与线程具有以下关系:

 /**
 * Thread relationship.
 *
 * @return \Illuminate\Database\Eloquent\Relations\BelongsTo
 *
 */
public function thread()
{
    return $this->belongsTo(Thread::class, 'thread_id', 'id');
}

I first run a query which gets all the threads for a specific user. 我首先运行一个查询,该查询获取特定用户的所有线程。 Once I get all the threads, I extract the id of each thread into an array. 一旦获得所有线程,就将每个线程的ID提取到数组中。 Now I want to get the latest message for each of the thread ids. 现在,我想获取每个线程ID的最新消息。 I've tried this: 我已经试过了:

Message::whereIn('thread_id', $threadIds)

But this gives me every single message related to each thread_id, looking at this I see that this could cause some major issues if say a few of the threads had thousands of messages related to it. 但这给了我每个与每个thread_id相关的消息,看着这个消息,我发现如果说几个线程有成千上万个与之相关的消息,可能会引起一些重大问题。 I've also tried the following: 我也尝试了以下方法:

Message::whereIn('thread_id', $threadIds)->take(1)

Which only returns one result which I also don't want. 仅返回一个我也不想要的结果。 I'm wondering if anyone knew of a way to get the latest message only for each of the $threadIds. 我想知道是否有人知道仅为每个$ threadIds获取最新消息的方法。

Here is an example of my schema with some sample data: 这是带有一些示例数据的我的架构的示例:

CREATE TABLE `messages` (
  `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
  `thread_id` int(10) unsigned NOT NULL,
  `user_id` int(10) unsigned NOT NULL,
  `body` text COLLATE utf8mb4_unicode_ci NOT NULL,
  `created_at` timestamp NULL DEFAULT NULL,
  `updated_at` timestamp NULL DEFAULT NULL,
  `deleted_at` timestamp NULL DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;

CREATE TABLE `threads` (
  `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
  `subject` varchar(255) COLLATE utf8mb4_unicode_ci NOT NULL,
  `created_at` timestamp NULL DEFAULT NULL,
  `updated_at` timestamp NULL DEFAULT NULL,
  `deleted_at` timestamp NULL DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;

INSERT INTO `threads` (`id`, `subject`, `created_at`, `updated_at`, `deleted_at`)
VALUES
    (1, 'test subject 1', '2019-02-01 00:32:56', '2019-02-01 00:32:56', NULL),
    (2, 'test subject 2', '2019-02-01 00:34:42', '2019-02-01 00:34:42', NULL);

INSERT INTO `messages` (`id`, `thread_id`, `user_id`, `body`, `created_at`, `updated_at`, `deleted_at`)
VALUES
    (1, 1, 2, 'test1', '2019-02-01 00:32:56', '2019-02-01 00:32:56', NULL),
    (2, 1, 1, 'test2', '2019-02-01 00:32:59', '2019-02-01 00:32:59', NULL),
    (3, 1, 2, 'test3', '2019-02-01 00:34:42', '2019-02-01 00:34:42', NULL),
    (4, 2, 1, 'test4', '2019-02-01 00:35:56', '2019-02-01 00:35:56', NULL),
    (5, 2, 3, 'test5', '2019-02-01 00:36:59', '2019-02-01 00:36:59', NULL),
    (6, 2, 1, 'test6', '2019-02-01 00:37:42', '2019-02-01 00:37:42', NULL);

Let's say I want to get the latest messages for threads with id: 1 and 2, I would like a result set like this: 假设我想获取ID为1和2的线程的最新消息,我想要这样的结果集:

id  thread_id   user_id body    created_at  updated_at  deleted_at
3   1   2   test3   2019-02-01T00:34:42Z    2019-02-01T00:34:42Z    (null)
6   2   1   test6   2019-02-01T00:37:42Z    2019-02-01T00:37:42Z    (null)

I've looked online for similar questions and I found one on stack overflow here which is pretty similar but it unfortunately went unanswered. 我在网上寻找类似的问题,但在这里发现了一个堆栈溢出问题 ,这很相似,但不幸的是没有得到解决。 Thanks in advance to anyone who takes a stab at answering this. 在此先感谢任何愿意回答这个问题的人。

I am not sure if this is the optimum way to do it. 我不确定这是否是最佳方法。 But I tried and it worked. 但是我尝试了并且成功了。

My approach is after getting the threadIds array, I run a loop and get the latest message for each thread. 我的方法是在获取threadIds数组之后,我运行一个循环并获取每个线程的最新消息。 Then I store that message in another array. 然后,我将该消息存储在另一个数组中。

$messages = array();
foreach($threadIds as $threadId)
{
    $message = Message::where('thread_id', $threadId)
               ->whereNotNull(`deleted_at`)
               ->orderby('created_at','desc')
               ->first();

    $messages[] = $message;
}
dd($messages);

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM