从联接的 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
架构 (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,我采用了他的演示
我有两个表:
进程
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 |
架构 (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,我采用了他的演示