从联接的 mysql 5.X 表中的每一行中至少获取最后 2 行

Get at least last 2 rows from each row in a joined mysql 5.X tables

我有两个表:

进程

idProcess data
1 XXXX
2 XXXX
... ...

追踪:

idTrace idProcess
1 1
2 1
3 1
4 2
5 2
6 2
7 2
... ...

需要每个 idProcess 的最后两个 idTrace,按 idTrace 降序排列:

idTrace idProcess
3 1
2 1
7 2
6 2
... ...

编辑 可以是跟踪中尚不存在的进程中的行...

由于您在问题中共享的所需输出仅包含来自您的 Tracings table 的列,因此您无需使用连接,而只需包含您的 Tracing table 以提高效率。

架构 (MySQL v5.5)

以下方法使用变量来确定顺序,并使用 where 子句来限制已排序的行号。

SET @row_num:=0;
SET @prev_grp:=NULL;

SELECT
     t.idTrace,
     t.idProcess  
FROM (
    SELECT 
        *, 
        @row_num:=(
             CASE 
                 WHEN @prev_grp<>idProcess THEN 1
                 ELSE @row_num+1
             END
        ) as rn,
        @prev_grp:=idProcess
    FROM 
        Tracings
    ORDER BY 
        idProcess,idTrace DESC
) t 
WHERE rn <=2
ORDER BY t.idProcess,t.idTrace DESC;

或作为一个查询

SELECT
     t.idTrace,
     t.idProcess  
FROM (
    SELECT 
        *,
        @row_num:=(
             CASE 
                 WHEN @prev_grp<>idProcess THEN 1
                 ELSE @row_num+1
             END
        ) as rn,
        @prev_grp:=idProcess
    FROM 
        Tracings
    CROSS JOIN (SELECT @row_num:=0,@prev_grp:=NULL) as vars 
    ORDER BY 
        idProcess,idTrace DESC
) t 

WHERE rn <=2
ORDER BY t.idProcess,t.idTrace DESC;
idTrace idProcess
3 1
2 1
7 2
6 2

View on DB Fiddle

架构 (MySQL v8.0)

您也可以使用 ROW_NUMBER 来实现此目的,例如

CREATE TABLE Processes (
  `idProcess` INTEGER,
  `data` VARCHAR(5)
);

INSERT INTO Processes
  (`idProcess`, `data`)
VALUES
  ('1', 'XXXX'),
  ('2', 'XXXXX');

CREATE TABLE Tracings (
  `idTrace` INTEGER,
  `idProcess` INTEGER
);

INSERT INTO Tracings
  (`idTrace`, `idProcess`)
VALUES
  ('1', '1'),
  ('2', '1'),
  ('3', '1'),
  ('4', '2'),
  ('5', '2'),
  ('6', '2'),
  ('7', '2');

查询#1

SELECT
     idTrace,
     idProcess
FROM (
    SELECT
         *,
         ROW_NUMBER() OVER (
             PARTITION BY idProcess
             ORDER BY idTrace DESC
         ) rn
    FROM
        Tracings
) t
WHERE rn <=2
ORDER BY t.idProcess,t.idTrace DESC;
idTrace idProcess
3 1
2 1
7 2
6 2

查询 #2 - 如果您需要进程中的数据 table

SELECT
     t.idTrace,
     t.idProcess,
     p.data
FROM 
Processes p 
INNER JOIN (
    SELECT
         *,
         ROW_NUMBER() OVER (
             PARTITION BY idProcess
             ORDER BY idTrace DESC
         ) rn
    FROM
        Tracings
) t ON p.idProcess = t.idProcess
WHERE rn <=2
ORDER BY t.idProcess,t.idTrace DESC;
idTrace idProcess data
3 1 XXXX
2 1 XXXX
7 2 XXXXX
6 2 XXXXX

View on DB Fiddle 让我知道这是否适合你。

MySQL5.x 可以使用相关子查询来查找要加入的行。

SELECT
  *
FROM
  Processes   p
LEFT JOIN
  Tracings   t
    ON  t.idProcess = p.idProcess
    AND t.yourTimestampColumn >= (
      SELECT yourTimestampColumn 
        FROM Tracings
       WHERE idProcess = p.idProcess
    ORDER BY yourTimestampColumn DESC
       LIMIT 1 OFFSET 1
    )

演示:https://www.db-fiddle.com/f/q1YCHFwX3zLiZ6xd52TdN6/0

  • 归功于@ggordon,我采用了他的演示