Mysql 订单依据和分组依据中的限制
我试图得到一组记录的子集,我已经看到了很多疯狂的解决方案,但是它们看起来太复杂了,有没有更有效的方法呢Mysql 订单依据和分组依据中的限制,mysql,sql,group-by,limit,greatest-n-per-group,Mysql,Sql,Group By,Limit,Greatest N Per Group,我试图得到一组记录的子集,我已经看到了很多疯狂的解决方案,但是它们看起来太复杂了,有没有更有效的方法呢 SELECT user_id, GROUP_CONCAT(item_id ORDER BY `timestamp`) AS items FROM wb_user_book_current_item GROUP BY user_id 这将返回所有用户的所有当前项目,到目前为止还可以。但我只想要最近的十件。将ORDER BY添加到GROUP_CONCAT会有所帮助,但它仍然无法提供最后十条记录
SELECT user_id, GROUP_CONCAT(item_id ORDER BY `timestamp`) AS items
FROM wb_user_book_current_item GROUP BY user_id
这将返回所有用户的所有当前项目,到目前为止还可以。但我只想要最近的十件。将ORDER BY添加到GROUP_CONCAT会有所帮助,但它仍然无法提供最后十条记录
编辑
如果我这样做并硬编码用户id,那么我就可以得到我想要的一个用户的结果,问题是组合它,这样我就不需要硬编码用户id,例如,可以只得到所有用户的最后十项
SELECT GROUP_CONCAT(cp2.item_id) AS items
FROM (SELECT cp.user_id, cp.item_id
FROM wb_user_book_current_item cp
WHERE cp.user_id=1 ORDER BY cp.`timestamp`
LIMIT 10) AS cp2
GROUP BY cp2.user_id
更新:我没有注意到组_CONCAT,因此您将不得不在confunction with LIMIT中使用子查询 使用限制
SELECT column_name(s)
FROM table_name
LIMIT number
这是一个困难的问题,但如何处理这个问题:
SELECT user_id, GROUP_CONCAT(item_id ORDER BY `timestamp`) AS items
FROM wb_user_book_current_item T
WHERE NOT EXISTS
(
SELECT 1
FROM wb_user_book_current_item T2
WHERE T2.user_id = T.user_id
ORDER BY T2.`timestamp` DESC
LIMIT 10,1
)
OR T.`timestamp` > (
SELECT T2.`timestamp`
FROM wb_user_book_current_item T2
WHERE T2.user_id = T.user_id
ORDER BY T2.`timestamp` DESC
LIMIT 10,1
)
GROUP BY user_id
当然,这假设同一用户不会有两行具有相同的时间戳
如果时间戳字段始终为正整数,则还可以替换NOT EXISTS…或使用合并:
原始答案,但显然MySQL不理解如何正确执行,并抱怨subselect返回多行。当然,我们需要多行;这是一个集体聚会。Grr
不幸的是,我认为没有真正的方法来使用子查询:
SELECT T.user_id,
GROUP_CONCAT((SELECT T2.item_id
FROM wb_user_book_current_item T2
WHERE T2.user_id = T.user_id
ORDER BY T2.`timestamp`
LIMIT 10)) AS items
FROM wb_user_book_current_item T
GROUP BY user_id
否则,在其他任何地方添加限制将限制组的数量,或限制表上的总记录集,而不是组-这两者都不是您试图实现的目标。尝试以下方法:
SELECT
user_id,
GROUP_CONCAT(item_id ORDER BY `timestamp`) AS items
FROM wb_user_book_current_item
GROUP BY user_id
LIMIT 0, 10
所以我在这里找到了一个很好的解决方案,效果很好 它是这样的,把所有这些放在一起:
SET @num := 0, @user_id := '';
SELECT cp2.user_id, CONCAT(cp2.item_id) AS items
FROM (
SELECT cp.user_id, cp.item_id,
@num := IF(@user_id = cp.user_id, @num + 1, 1) AS row_number,
@user_id := cp.user_id AS dummy
FROM wb_user_curent_item AS cp
ORDER BY cp.user_id ASC, cp.`timestamp` DESC
) AS cp2 WHERE cp2.row_number <= 10
GROUP BY cp2.user_id
所以基本上它只是使用num增量来限制记录,而不是使用limit
关于用户id、时间戳、项目id的索引将有助于提高效率。也许您必须在末尾设置限制0,10?同意,我没有看到组concat-op必须与限制一起使用子查询,因此SELECT会返回多行,但是CONCAT发生在这之后,所以我得到了一个多行错误,因为它试图将所有内容都放在一个记录中。仍在努力以其他方式将其浓缩,但似乎还没有找到方法。这将限制最终结果的数量,而不是每个用户的项目结果。
SET @num := 0, @user_id := '';
SELECT cp2.user_id, CONCAT(cp2.item_id) AS items
FROM (
SELECT cp.user_id, cp.item_id,
@num := IF(@user_id = cp.user_id, @num + 1, 1) AS row_number,
@user_id := cp.user_id AS dummy
FROM wb_user_curent_item AS cp
ORDER BY cp.user_id ASC, cp.`timestamp` DESC
) AS cp2 WHERE cp2.row_number <= 10
GROUP BY cp2.user_id
SELECT
i.user_id,
GROUP_CONCAT(i.item_id ORDER BY i.timestamp) AS items
FROM
( SELECT DISTINCT user_id
FROM wb_user_book_current_item
) AS du
JOIN
wb_user_book_current_item AS i
ON i.user_id = du.user_id
AND i.timestamp <= COALESCE(
( SELECT i2.item_id
FROM wb_user_book_current_item AS i2
WHERE i2.user_id = du.user_id
ORDER BY i2.timestamp ASC
LIMIT 1 OFFSET 9
)
, '2038-01-19 03:14:07')
GROUP BY
i.user_id ;