sqlite3 按最大值查询并按第二个因素过滤
Posted
技术标签:
【中文标题】sqlite3 按最大值查询并按第二个因素过滤【英文标题】:sqlite3 query by max and filter by second factor 【发布时间】:2015-12-28 04:23:42 【问题描述】:我有:
TABLE MESSAGES
message_id | conversation_id | from_user | timestamp | message
我想要:
1. SELECT * WHERE from_user <> id
2. GROUP BY conversation_id
3. SELECT in every group row with MAX(timestamp) **(if there are two same timestamps in a group use second factor as highest message_id)** !!!
4. then results SORT BY timestamp
有结果:
2|145|xxx|10000|message
6|1743|yyy|999|message
7|14|bbb|899|message
淘汰
1|145|xxx|10000|message <- has same timestamp(10000) as message(2) belongs to the same conversation(145) but message id is lowest
5|1743|me|1200|message <- has message_from == me
具有相同时间戳的示例组
我想从这个组第 3 行,但我从查询中得到第 2 行
SELECT max(message_timestamp), message_id, message_text, message_conversationId
FROM MESSAGES
WHERE message_from <> 'me'
GROUP BY message_conversationId
ORDER by message_Timestamp DESC
我的想法是从 message_id 和时间戳进行联合,然后得到最大值???
【问题讨论】:
用样本数据准备sqlfiddle.com 投票将其迁移到 DBA.SE(因为它已在那里交叉发布:dba.stackexchange.com/questions/116123/…),因此它们可以合并。 【参考方案1】:您的查询基于 GROUP BY
的非标准使用(我认为 SQLite 仅允许与 mysql 兼容),我完全不确定它是否会一直产生确定的结果。
另外,它在连接列上使用MAX()
。除非您以某种方式确保两个(连接的)列具有固定宽度,否则结果也不会因此而准确。
我会这样写查询:
SELECT
m.message_timestamp,
m.message_id,
m.message_text,
m.message_conversationId
FROM
( SELECT message_conversationId -- for every conversation
FROM messages as m
WHERE message_from <> 'me'
GROUP BY message_conversationId
) AS mc
JOIN
messages AS m -- join to the messages
ON m.message_id =
( SELECT mi.message_id -- and find one message id
FROM messages AS mi
WHERE mi.message_conversationId -- for that conversation
= mc.message_conversationId
AND mi.message_from <> 'me'
ORDER BY mi.message_timestamp DESC, -- according to the
mi.message_id DESC -- specified order
LIMIT 1 -- (this is the one part)
) ;
【讨论】:
感谢@ypercube 的帮助!!!在我的情况下,group by 与聚合(最大)一起使用 - 你不要在“mc”上使用任何聚合......你的意思是“我完全不确定它会一直产生确定的结果”是什么意思。我看到你使用限制 & 订单 & 加入 - 丹尼尔使用最大 & 加入 - 你使用不同类型的写查询 ""JOIN name AS ON var = SELECT" 丹尼尔在他的例子中 "JOIN (SELECT) AS name =" 对我来说是如果你在 AS JOIN 上使用一些魔法 .. 等等,阅读查询会变得更加困难 :) 我看到更多图形 - 切割/创建/拆分/合并表:D - 所以很高兴看到一些图形解释这样一个复杂的查询:) 您的查询有GROUP BY message_conversationId
,同时有SELECT max(message_timestamp), message_id, message_text
。如果有很多行具有相同的conversationId
,则返回最大时间戳。没关系。但是将返回所有message_id
中的哪一个? message_text
中的哪一个?您假设它将是具有最大时间戳的那些,但我完全不确定它是否会这样。它可能是不同的 message_id(不是最新的)和不同的文本。
是的,message_from <> 'me'
需要两次。
但不管有没有我在 5000 行中得到了相同的结果【参考方案2】:
好吧,这比我想象的要简单:
基本上改变选择:
max(message_timestamp)
到:
max(message_timestamp || message_id)
or max(message_timestamp + message_id)
所以它会搜索时间戳和message_id的最大串联
ps。挖掘后 - 只有当消息 id 随时间戳增长时它才有效(保留插入顺序)
编辑:
编辑2:
那么为什么它有效?
SELECT max(message_timestamp+message_id), message_timestamp, message_id, message_conversationId, message_from,message_text
FROM MESSAGES
WHERE message_conversationId = 1521521
AND message_from <> 'me'
ORDER by message_Timestamp DESC
【讨论】:
时间戳上的字符串比较可能是错误的 (10
9)。
select '20' > '100' 返回真,所以连接不起作用,除非你能确保转换成字符串后的长度没有两列的长度差异。
是的,但我得到的时间戳和 message_id 一样长,那么如何添加这两个值
edit2 有效,因为时间戳是一个相对较大的数字,但请求 ID 很小。但是当请求 id 增长并且时间戳变大时,它就会出现问题,即它获得请求 id 的最大值然后时间戳。你最好防止这种情况,因为 edit2 有条件地为“真”,并且在编程上不正确。
虽然请求 id 大于时间戳的情况很少发生,因为表很少这么大【参考方案3】:
尝试下面的sql,按两次分组达到你的目的。
select m.*
from
Messages m
-- 3. and then joining to get wanted output columns
inner join
(
--2. then selecting from this max timestamp - and removing duplicates
select conversation_id, max(timestamp), message_id
from
(
-- 1. first select max message_id in remainings after the removal of duplicates from mix of cv_id & timestamp
select conversation_id, timestamp, max(message_id) message_id
from Messages
where message <> 'me'
group by conversation_id, timestamp
) max_mid
group by conversation_id
) max_mid_ts on max_mid_ts.message_id = m.message_id
order by m.message_id;
http://goo.gl/MyZjyU
【讨论】:
是的,它有效,但它与我的方法有何不同?我创建了新列,我得到了最大值(好吧,我可能理解 10 + 100 != 101 + 00 但那两个是 10100) 感谢我在 where clausule 中插入 :) 并按 .. 设置顺序,但我试图理解您的查询 如果你像字符串一样添加这些字段,问题是10||20 > 10||101 => '1020' > '10101',它最终选择了较低的消息ID。跨度> 1.首先,在从 cv_id 和时间戳的混合中删除重复项后,在剩余部分中选择 max message_id 2.然后你从这个最大时间戳中选择 - 并删除重复项以上是关于sqlite3 按最大值查询并按第二个因素过滤的主要内容,如果未能解决你的问题,请参考以下文章
orderByChild() 如果值相同,如何按第二个变量排序?
按第二个值对元组列表进行排序,reverse=True,然后按 key,reverse=False
如何按第一个值和第二个值对 pair<int, char> 的向量进行排序? [复制]
有一个form,包含两个text,和两个按钮,当用户按第一个按扭时把数据提交到url1,按第二个按钮提交到url2,怎么实现呀?