gpt4 book ai didi

sql - 在复杂的 mysql 分页查询逻辑方面需要帮助

转载 作者:行者123 更新时间:2023-11-29 01:00:13 28 4
gpt4 key购买 nike

好的,我对如何有效地构建分页系统感到很困惑。问题是系统不是典型的,不会以固定的间隔进行,例如每页 10 次。问题是,消息可以有回复,因此共享相同的 reply_chunk_id (reply_id)。我不希望消息被切断,但这样做似乎越来越复杂。

我检索消息的初始查询是这样的,无论回复在表中的哪个位置,它都会将消息作为一个分组进行检索,它会根据时间戳按降序依次与具有相同 reply_chunk_id 的相应消息分组

SELECT m.timestamp, m.user, m.message, g.grp_timestamp,m.reply_chunk_id
FROM shoutbox AS m JOIN
(SELECT reply_chunk_id, MIN(timestamp) AS grp_timestamp
FROM shoutbox
GROUP BY reply_chunk_id) AS g ON m.reply_chunk_id = g.reply_chunk_id
WHERE m.topic_id = ?
ORDER BY g.grp_timestamp DESC, g.reply_chunk_id, m.timestamp DESC limit ?, ?

我想我需要另一个查询来检索此查询的限制参数,因为页面不会按固定间隔显示,因此需要唯一的起点和终点,具体取决于您选择的页面。我正在考虑选择一个限制,例如 $limit 为 10,然后转到最接近的四舍五入的消息数。因此,例如,如果您收到第 10 条消息并且该组还有 2 条回复,您将检索 12 条消息。

我遇到的问题是构造此限制检索查询的逻辑。我将不得不以某种方式从该主题的第一条消息开始,计算它的所有回复,转到第二条,计算所有回复,直到达到四舍五入的数字,然后输出它。

真正麻烦的是说你要换页,你怎么跳到上一页的终点,或者你跳过一页直接从第1-3页开始.答案是你不能,所以你每次都必须从该主题的第一条消息开始,计算所有回复,继续对每条消息做同样的事情,直到你达到你的四舍五入数字,以某种方式表明你已经通过了第一页,然后继续,直到到达您想要的页面消息。我真的不确定该怎么做,或者这是否是最好的方法,所以非常感谢任何帮助或建议。

表格设计

CREATE TABLE IF NOT EXISTS `shoutbox` (
`id` int(5) NOT NULL AUTO_INCREMENT,
`timestamp` int(11) NOT NULL,
`user` varchar(25) CHARACTER SET utf8 COLLATE utf8_unicode_ci NOT NULL
DEFAULT 'anonimous',
`message` varchar(2000) CHARACTER SET utf8 COLLATE utf8_unicode_ci NOT NULL,
`topic_id` varchar(35) NOT NULL,
`reply_chunk_id` varchar(35) NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1 AUTO_INCREMENT=7 ;

最佳答案

编辑:有时间测试,新检查的单一查询解决方案

SELECT timestamp, user, message, grp_timestamp,reply_chunk_id
FROM (
SELECT totalresult.*,
@page := IF(
(
@subcounter >= @perpage -- if we have more then @perpage
AND
reply_chunk_id != @old_chunk_id -- AND we are on a reply_chunk border
)
OR
(
@subcounter >= @absolutemax -- the upper maximum is reached
)
OR
(
(@subcounter + grp_messagecount > @absolutemax) -- next replychunk would put us over the top
AND
(grp_messagecount <= @absolutemax) -- next replyhunk would fit in a single pagenumber
AND
(@subcounter >= @allowprematurebreak) -- and we have enough items to qualify for a page
),
@page + 1 + (@subcounter:=0), -- increment page and reset counter
@page) as page, -- otherwise keep the same @page
@subcounter := @subcounter + 1 as counter, -- increment counter
@old_chunk_id := reply_chunk_id as reply_chunk -- store previous reply chunk
FROM (
SELECT
m.timestamp, m.user, m.message, g.grp_timestamp,m.reply_chunk_id, g.grp_messagecount
FROM shoutbox AS m
JOIN (
SELECT
reply_chunk_id,
MIN(timestamp) AS grp_timestamp,
COUNT(*) AS grp_messagecount
FROM shoutbox
GROUP BY reply_chunk_id
) AS g ON m.reply_chunk_id = g.reply_chunk_id
WHERE m.topic_id = ?
ORDER BY g.grp_timestamp DESC, g.reply_chunk_id, m.timestamp DESC
) AS totalresult
JOIN (
SELECT
@page :=0, -- the page number / counter
@old_chunck_id :=0, -- placeholder for old reply_chunk so we can detect boundaries
@subcounter :=0, -- counter for number of actual messages
@perpage :=10, -- preferred amount of messages per page
@absolutemax :=20, -- allow breaking in reply_chunk if absolutemax is reached
@allowprematurebreak :=5 -- minimum of messages per page, used if we can let the
-- next chunk see whole on the next page
) AS void
) AS paginatedresult
WHERE page = <pagenumber>

我已经添加了一些设置作为变量,以方便和更易读地绑定(bind)参数。关于性能:对它进行基准测试,它很可能做得很好(当然是因为它受到主题的限制)。如果没有,您的解决方案将获取此内部子查询的输出:

          SELECT
reply_chunk_id,
MIN(timestamp) AS grp_timestamp,
COUNT(*) AS grp_messagecount
FROM shoutbox
GROUP BY reply_chunk_id

并将确定在哪里中断的逻辑移动到一些脚本逻辑中,这些脚本逻辑决定要查询哪个 reply_chunk_id。

关于sql - 在复杂的 mysql 分页查询逻辑方面需要帮助,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3817332/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com