MySQL:如何从数组中检索n(数量)数据?

时间:2014-06-23 01:15:53

标签: php mysql laravel laravel-4 eloquent

我有一个消息表。

+----+---------+----------+
| id | conv_id | body     |
+----+---------+----------+
|  1 |       1 |     haha |
|  2 |       1 |     blabl|
| ...|     ... |    ...   |
|  25|       2 |     hehe |
+----+---------+----------+

... =其余的消息,其中conv_id为2或1或3或n。

假设我有conv_id = array(2,1),我希望在与conv_id中的一系列ID匹配后获取10条消息,所以我做了

select * from `messages` where `conv_id` in (2, 1) order by `created_at` desc limit 10

上面的sql给了我10条消息 匹配conv_ids并获取所有组合消息。但是,这是我想要的 NOT 。相反,我想要10条消息的每个 conv_id匹配。

我如何获得10条的每条转化符号?请不要PHP for循环。谢谢!

注意:数组conv_id可以轻松扩展,以包含彼此独有的许多其他值,而不仅仅是2或1。


对于Laravel Eloquent的回答,

奖励积分!以下是详细信息:

  1. 通过Conversations链接的两个模型,对话和消息,有很多消息和消息属于对话。
  2. 我上面的sql是从Messages::with('User')->whereIn('conv_id',$conv_id)->orderBy('created_at','desc')->take(10);
  3. 翻译而来的

3 个答案:

答案 0 :(得分:1)

我认为Jared是对的但是如果你可以在表中添加另一列,解决方案会更有效率。添加一个列,指示每个conv_id的消息编号(最早将有1,最新的将具有会话消息的数量)。之后,您可以使用HAVING子句扫描表格两次来实现目标。

SELECT * FROM messages JOIN
  (SELECT conv_id, MAX(msg_no) FROM messages WHERE conv_id IN (2,1) GROUP BY conv_id) as M 
ON messages.conv_id=M.conv_id HAVING messages.msg_no > M.msg_no-10

答案 1 :(得分:1)

另一种可能性。使用group_concat - substring_index技巧获取最后一个conv_ids及其第10个(消息)id,并重新加入message-table。

SELECT `messages`.*
FROM (
    SELECT 
    conv_id,
    substring_index(
        substring_index(
            group_concat(`messages`.id),
            ',',
            10
        ),
        ',',
        -1
    ) AS lastMessageId
    FROM `messages` 
    WHERE `conv_id` in (2, 1)
    GROUP BY `conv_id`
) AS msub
INNER JOIN `messages` ON `messages`.conv_id = msub.conv_id AND `messages`.id <= msub.lastMessageId

答案 2 :(得分:0)

警告:此方法可能有误。我试图对其进行验证,并在得出结论后对其进行更新

昨天我刚从deczo Getting just the latest value on a joined table with Eloquent的答案中学到了关于雄辩关系的新内容。而且我认为我们也可以根据你的情况调整它。

你本来想要做的事情,我把我的观点视为:

  • 包含许多消息的对话模型。
  • 但我每次会话只需要10条最新消息。所有人都热切期待。

在Eloquent中,我可能会按照以下方式做点什么:

Conversation::with('messages')->whereIn('conv_id', [1, 2])->get();

但我注意到你的两个问题。

  • 我假设您没有另一张名为对话的表格。
  • 上述代码并不限制每次会话的消息数量。

所以我决定这里应该是两个模型,一个叫做Message,另一个叫做Conversation。 两者都调用同一个表,但我们会告诉Eloquent使用不同的列作为主键。 因此,为了获得对话模型,我在我的newQuery函数中添加了distinct(),并仅选择conv_id,因为这是关于对话的唯一信息。

所以最后我有这个:

<强>模型/ Message.php

class Message extends Eloquent
{
    protected $table = 'messages';
    protected $primaryKey = 'id';
    public $timestamps = false;
}

<强>模型/ Conversation.php

class Conversation extends Eloquent
{
    protected $table = 'messages';
    protected $primaryKey = 'conv_id';
    public $timestamps = false;

    public function newQuery($excludeDeleted = true)
    {
        return parent::newQuery()
            ->select('conv_id')
            ->distinct();
    }

    public function messages()
    {
        return $this->hasMany('Message', 'conv_id')
            ->orderBy('id', 'desc')
            ->take(10);
    }
}

现在我能做到:

Conversation::with('messages')->whereIn('conv_id', [1, 2])->get();

它为我提供了conv_id 1和2的对话列表,以及每个对话的10条最新消息。

这是我第一次这样做。所以我进行了代码测试,但它确实有效。


更新:我的回答中的代码只执行这两个查询(从DB :: getQueryLog()检索):

select distinct `conv_id` from `messages` where `conv_id` in (?, ?);
select * from `messages` where `messages`.`conv_id` in (?, ?) order by `id` desc limit 10;