我有一个具有以下结构的SQL表:
id Integer, (represents a userId)
version Integer,
attribute varchar(50)
所以一些示例行是:
4, 1, 'test1'
4, 2, 'test2'
4, 3, 'test3'
我需要按以下格式生成输出:
4, 1, 'test1', 'test1'
4, 2, 'test2', 'test1'
4, 3, 'test3', 'test2'
所以输出的格式是:
id Integer,
version Integer,
attribute_current varchar,
attribute_old varchar
我已经尝试了以下内容:
select versionTest.id, versionTest.version, versionTest.attribute, maxVersionTest.attribute
from versionTest
inner join
versionTest maxVersionTest
ON
versionTest.id = versionTest.id
AND
versionTest.version =
(Select max(version) currentMaxVersion
from versionTest maxRow
where maxRow.id = id);
执行上述查询,但返回不正确的结果。它只返回最大版本,而不是返回所有版本的行。
有关如何修复查询以产生正确结果的任何想法?谢谢!
注意 - 版本号不保证从1开始是连续的。我的实际数据库有一些不寻常的版本号(即用户7有版本3和15,没有版本4,5,6等...)。
答案 0 :(得分:1)
既然你提到过:
版本号不保证从1开始是连续的。我的实际数据库有一些不寻常的版本号(即用户7有版本3和15,没有版本4,5,6等...)
MySQL不像任何其他RDBMS那样支持窗口函数,你仍然可以模拟如何创建序列号并用作连接列来获取前面的行。前,
SELECT a.ID, a.Version, a.attribute attribute_new,
COALESCE(b.attribute, a.attribute) attribute_old
FROM
(
SELECT ID, version, attribute,
@r1 := @r1 + 1 rn
FROM TableName, (SELECT @r1 := 0) b
WHERE ID = 4
ORDER BY version
) a
LEFT JOIN
(
SELECT ID, version, attribute,
@r2 := @r2 + 1 rn
FROM TableName, (SELECT @r2 := 0) b
WHERE ID = 4
ORDER BY version
) b ON a.rn = b.rn + 1
答案 1 :(得分:1)
SELECT a.*, COALESCE(b.attribute,a.attribute) attribute_old
FROM
( SELECT x.*
, COUNT(*) rank
FROM versiontest x
JOIN versiontest y
ON y.id = x.id
AND y.version <= x.version
GROUP
BY x.id
, x.version
) a
LEFT
JOIN
( SELECT x.*
, COUNT(*) rank
FROM versiontest x
JOIN versiontest y
ON y.id = x.id
AND y.version <= x.version
GROUP
BY x.id
, x.version
) b
ON b.id = a.id
AND b.rank = a.rank-1;
示例输出(DEMO):
+----+---------+-----------+------+---------------+
| id | version | attribute | rank | attribute_old |
+----+---------+-----------+------+---------------+
| 4 | 1 | test1 | 1 | test1 |
| 4 | 5 | test2 | 2 | test1 |
| 4 | 7 | test3 | 3 | test2 |
| 5 | 2 | test3 | 1 | test3 |
| 5 | 3 | test4 | 2 | test3 |
| 5 | 8 | test5 | 3 | test4 |
+----+---------+-----------+------+---------------+
答案 2 :(得分:0)
如果版本号总是增加1
,您可以:
select cur.id
, cur.version
, cur.attribute
, coalesce(prev.attribute, cur.attribute)
from versionTest
left join
versionTest prev
on prev.id = cur.id
and prev.version = cur.version + 1
答案 3 :(得分:0)
你可以试试......
SELECT ID,
VERSION,
ATTRIBUTE,
(SELECT ATTRIBUTE
FROM VERSIONTEST V3
WHERE V3.ID = V1.ID AND
V3.VERSION = (SELECT MAX(VERSION)
FROM VERSIONTEST V2
WHERE V2.ID = V1.ID AND
V2.VERSION < V1.VERSION)) AS PREVIOUSATTRIBUTE
FROM VERSIONTEST V1;
如果版本值按数字顺序排列。
答案 4 :(得分:0)
我认为最简单的表达方式是使用相关的子查询:
select id, version, attribute as attribute_current,
(select attribute
from VersionTest vt2
where vt2.id = vt.id and vt2.version < vt.version
order by vt2.version
limit 1
) as attribute_prev
from VersionTest vt
此版本将NULL
作为第一行的prev值。如果你真的想重复它:
select id, version, attribute as attribute_current,
coalesce((select attribute
from VersionTest vt2
where vt2.id = vt.id and vt2.version < vt.version
order by vt2.version
limit 1
), vt.attribute
) as attribute_prev
from VersionTest vt