基本上,我有一个表messages
,其中的user_id
字段标识创建消息的用户。
当我显示两个用户之间的对话(一组消息)时,我希望能够通过来对消息进行分组user_id
,但要采用一种棘手的方式:
假设有一些消息(按排序created_at desc
):
id: 1, user_id: 1
id: 2, user_id: 1
id: 3, user_id: 2
id: 4, user_id: 2
id: 5, user_id: 1
我想按以下顺序获得3个消息组: [1,2], [3,4], [5]
它应该按 user_id 分组,直到看到一个不同的分组,然后再按该分组。
我正在使用PostgreSQL,并且很乐意使用特定于它的东西,无论哪种都能提供最佳性能。
@Igor提供了一种很好的带有窗口函数的纯SQL技术。
然而:
我想按以下顺序获得3个消息组:[1,2],[3,4],[5]
要获取请求的订单,请添加ORDER BY min(id)
:
SELECT array_agg(id) AS ids
FROM (
SELECT id
,user_id
,row_number() OVER (ORDER BY id) -
row_number() OVER (PARTITION BY user_id ORDER BY id) AS grp
FROM messages
ORDER BY id) t -- for ordered arrays in result
GROUP BY grp, user_id
ORDER BY min(id);
SQL提琴。
增加几乎不能保证另一个答案。更重要的问题是:
我使用的是PostgreSQL,并且很乐意使用特定于它的东西,无论哪种都能提供 最佳性能 。
纯SQL都很好,而且很闪亮,但是过程 服务器端函数 对于此任务来说 要 快得多。尽管从程序上处理行 通常较慢 ,但 plpgsql
赢得了这场竞争的 青睐 ,因为它可以通过 单个 表扫描和 单个 ORDER BY
操作来完成:
CREATE OR REPLACE FUNCTION f_msg_groups()
RETURNS TABLE (ids int[]) AS
$func$
DECLARE
_id int;
_uid int;
_id0 int; -- id of last row
_uid0 int; -- user_id of last row
BEGIN
FOR _id, _uid IN
SELECT id, user_id FROM messages ORDER BY id
LOOP
IF _uid <> _uid0 THEN
RETURN QUERY VALUES (ids); -- output row (never happens after 1 row)
ids := ARRAY[_id]; -- start new array
ELSE
ids := ids || _id; -- add to array
END IF;
_id0 := _id;
_uid0 := _uid; -- remember last row
END LOOP;
RETURN QUERY VALUES (ids); -- output last iteration
END
$func$ LANGUAGE plpgsql;
称呼:
SELECT * FROM f_msg_groups();
我在具有EXPLAIN ANALYZE
6万行的类似现实生活中的表上进行了快速测试(执行几次,选择最快的结果以排除兑现影响):
SQL:
总运行时间:1009.549毫秒
Pl / pgSQL:
总运行时间: 336.971毫秒
还请考虑以下密切相关的问题:
问题内容: 在Java 8中,如何通过检查每个对象的属性的不同性来使用API 过滤集合? 例如,我有一个对象列表,我想删除同名的人, 将对对象使用默认的相等性检查Person,所以我需要类似的东西, 不幸的是,该方法没有这种过载。如果不修改类内部的相等性检查,是否可以简洁地做到这一点? 问题答案: 考虑做一个有状态过滤器。这是一个函数,该函数返回一个谓词,该谓词保持先前状态的状态,并返回是否第一次
我已经创建了一个类get set,但是调试显示v有一个对象类型,如何将对象分配到属性中?有什么想法吗?
我正在写基本的用户注册页面,我的注册页面包含:用户邮件,密码,计划类型。计划类型有三个计划。三种方案是:基本方案、银方案和金方案。 register_main.php是将用户信息存储在MySQL中。 我遇到的问题是,当我点击基本或银或黄金计划,页面将转到注册的主页。我只希望在他们单击“登录”时将用户信息发送到服务器。 有人能帮我解决这个问题吗? 超文本标记语言代码: register_main.p
什么类型的价值适合于此?值应该只是布尔值(根据主模式),或者可以是布尔值或字符串(在正确的地方引用基资源)。我使用的JSON验证器不允许值为布尔值以外的任何值,我在JSON规范中搜索了很多,但没有关于它的信息。
问题内容: 如何转换为: 到这个: 使用javascript或下划线 问题答案: 假设原始列表包含在名为的变量中:
我需要使用特定对象的属性(