【问题标题】:如何选择 mysql 表中的倒数第二行,按列分组?
【发布时间】:2022-01-22 22:51:49
【问题描述】:

结构是:

CREATE TABLE current
(
   id BIGINT NOT NULL AUTO_INCREMENT,
   PRIMARY KEY(id),
   symbol VARCHAR(5),
   UNIQUE (id), INDEX (symbol)
) ENGINE MyISAM;
id symbol
1 A
2 B
3 C
4 C
5 B
6 A
7 C
8 C
9 A
10 B

我正在使用以下

SELECT * 
FROM current
WHERE id
IN 
(
    SELECT MAX(id)
    FROM current
    GROUP BY symbol
)

返回表中的最后一条记录。

id symbol
8 C
9 A
10 B

如何以类似的方式返回倒数第二个结果?

我知道我需要

ORDER BY id DESC LIMIT 1,1

在某个地方,但我的 foo 很弱。

我想回来

id symbol
5 B
6 A
7 C

【问题讨论】:

  • 也许您需要 TOP 2,然后 LIMIT 1 以获得 2 个最佳结果中的第一个。当然,您必须牢记秩序。我不知道数据集,但我认为它对您的逻辑很有用
  • 发布示例数据和预期结果以阐明您想要什么。
  • 想用一个例子来详细说明? mysql 不是我的第一语言。

标签: mysql sql group-by


【解决方案1】:

对于8.0之前的MySql版本,在WHERE子句中使用子查询过滤掉每个符号的最大id,然后聚合:

SELECT MAX(id) id, symbol
FROM current
WHERE id NOT IN (SELECT MAX(id) FROM current GROUP BY symbol)
GROUP BY symbol
ORDER BY id;

请参阅demo

【讨论】:

  • 这似乎工作得最快,但如果我要向表中添加另一列(例如 TIMESTAMP),则这些列对于 id 和符号是正确的,但 TIMESTAMP 看起来来自第一个行。
  • @weirdbeard 您不能在聚合查询中添加列。即使它运行(大多数数据库甚至不接受它),列值也是任意的。如果你想要其他列,你可以这样做:dbfiddle.uk/…
【解决方案2】:
SELECT * 
FROM current
WHERE id IN (
  SELECT DISTINCT T.id FROM current AS T
  WHERE id=(
    SELECT id FROM current
    WHERE symbol=T.symbol
    ORDER BY id DESC LIMIT 1,1
  )
)

【讨论】:

  • 感谢您的回复,但是这些仅返回表格的倒数第二行,而不是按“符号”分组的所有行。
  • @weirdbeard 我已经编辑了我的代码。有用吗?
  • 它似乎有效,但需要 5 分钟才能完成。该表有几百万条记录。
【解决方案3】:

如果您的 MySql 可以使用 ROW_NUMBER,则很容易。 (MySql 8)
只需让它降序排序,然后取第二个。

WITH CTE AS (
    SELECT *
    , ROW_NUMBER() OVER (PARTITION BY symbol ORDER BY id DESC) AS symbol_rn
    FROM current
) 
SELECT id, symbol
FROM CTE
WHERE symbol_rn = 2
ORDER BY id;

在 MySql 7.5 中,您可以简单地对符号进行自连接,并按分组。
然后倒数第二个将有 1 个更高的 id。

SELECT c1.id, c1.symbol
FROM current c1
LEFT JOIN current c2
  ON c2.symbol = c1.symbol
 AND c2.id >= c1.id
GROUP BY c1.id, c1.symbol
HAVING COUNT(c2.id) = 2
ORDER BY c1.id;
id symbol
5 B
6 A
7 C

db小提琴here

性能将真正受益于符号索引。

【讨论】:

  • 您的第一个解决方案(MySql 8)按预期返回结果,是迄今为止最好的答案。我确实有一个符号索引,但是查询仍然需要大约 11 秒才能运行。
  • 很有趣,但不知道如何加快速度。顺便说一句,那么第二个解决方案有多快?
  • 完成后我会通知你的 ;-)
【解决方案4】:

你可以试试这个;

SELECT * 
FROM current
WHERE id
IN (SELECT MAX(id)
FROM current
GROUP BY symbol)
ORDER BY id DESC LIMIT 1,3

限制 1,3 说;获取最后 3 个结果,不包括最后一个结果。您可以更改数字。

【讨论】:

  • 这不会返回 OP 的预期结果:dbfiddle.uk/…
  • 我认为因为我们使用的是 group by,所以它在链接中的示例中给出了该结果。将id值为7的数据的符号改为D再试一次
  • 不是,是因为你的回答错了。
  • 这取决于您查看问题的位置
  • 不,这取决于了解需求并了解您的代码的作用。如果您发现从代码中得到的结果不是应有的结果,那么您就知道自己错了。
猜你喜欢
  • 2019-12-18
  • 2021-04-01
  • 1970-01-01
  • 1970-01-01
  • 2019-12-04
  • 2017-01-16
  • 2015-01-03
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多