SQL - 版本比较
SQL - Version comparison
这是我的第一个问题。
我正在构建一个 SQL 查询,我需要在其中验证对象 B 的版本始终低于或等于对象 A 的版本。这是一个 link table,这里有一个例子:
查询是:
SELECT *
FROM TABLE
WHERE B_VERSION <= A_VERSION
如您所见,它适用于前两行,但不适用于第三行,因为 AA0 被检测为小于 H08 而它不应该(当我们到达 Z99 时,下一个版本号是 AA0 所以<= 运算符不再起作用)。
所以我想做一些事情,比如解析版本来比较版本中有多少字母,只有当两个版本的字母数量相同时,我才使用 <= 运算符。
不过我不知道如何在 SQL 查询中执行此操作。在 google 上也没有找到任何有用的东西。你有解决办法吗?
提前致谢
解决这个问题的关键是函数PATINDEX。您可以找到更多信息 here.
此查询采用 A_VERSION 的值并查找第一次出现的数字。然后使用这个位置将值分成两部分。第一部分用空格填充到右边,因为它是字母,而第二部分用零('0')填充到右边,因为它是数字。
B_VERSION 发生相同的过程。
请注意,在此示例中,假定每个部分最多为 5 个字符,因此这适用于从 A0 到 ZZZZZ99999 的版本。随时根据需要进行调整。
SELECT *
FROM TABLE
WHERE RIGHT(SPACE(5)
+ SUBSTRING(A_VERSION,
1,
PATINDEX('%[0-9]%', A_VERSION) - 1), 5)
+ RIGHT(REPLICATE('0', 5)
+ SUBSTRING(A_VERSION,
PATINDEX('%[0-9]%', A_VERSION),
LEN(A_VERSION)), 5)
<= RIGHT(SPACE(5)
+ SUBSTRING(B_VERSION,
1,
PATINDEX('%[0-9]%', B_VERSION) - 1), 5)
+ RIGHT(REPLICATE('0', 5)
+ SUBSTRING(B_VERSION,
PATINDEX('%[0-9]%', B_VERSION),
LEN(B_VERSION)) ,5)
如果你要在很多地方做这个操作,你可以考虑为这个操作创建一个函数。
希望对您有所帮助。
非常感谢!它有很大帮助,但是我使用的是 sql 开发人员,我不能将 PATINDEX 与该软件一起使用,我发现等效项是 REGEXP_INSTR,它的工作方式非常相似。
我用这个算法过滤掉 VERSION_B 中字母多于 VERSION_A 的行,然后过滤掉 VERSION_B 大于 [=17= 的行] 当他们有相同数量的字母时:
WHERE
(REGEXP_INSTR(VERSION_B, '[0-9]') < REGEXP_INSTR(VERSION_A, '[0-9]')) OR
(REGEXP_INSTR(VERSION_B, '[0-9]') = REGEXP_INSTR(VERSION_A, '[0-9]') AND VERSION_B <= VERSION_A)
这是我的第一个问题。
我正在构建一个 SQL 查询,我需要在其中验证对象 B 的版本始终低于或等于对象 A 的版本。这是一个 link table,这里有一个例子:
查询是:
SELECT *
FROM TABLE
WHERE B_VERSION <= A_VERSION
如您所见,它适用于前两行,但不适用于第三行,因为 AA0 被检测为小于 H08 而它不应该(当我们到达 Z99 时,下一个版本号是 AA0 所以<= 运算符不再起作用)。
所以我想做一些事情,比如解析版本来比较版本中有多少字母,只有当两个版本的字母数量相同时,我才使用 <= 运算符。
不过我不知道如何在 SQL 查询中执行此操作。在 google 上也没有找到任何有用的东西。你有解决办法吗?
提前致谢
解决这个问题的关键是函数PATINDEX。您可以找到更多信息 here.
此查询采用 A_VERSION 的值并查找第一次出现的数字。然后使用这个位置将值分成两部分。第一部分用空格填充到右边,因为它是字母,而第二部分用零('0')填充到右边,因为它是数字。
B_VERSION 发生相同的过程。
请注意,在此示例中,假定每个部分最多为 5 个字符,因此这适用于从 A0 到 ZZZZZ99999 的版本。随时根据需要进行调整。
SELECT *
FROM TABLE
WHERE RIGHT(SPACE(5)
+ SUBSTRING(A_VERSION,
1,
PATINDEX('%[0-9]%', A_VERSION) - 1), 5)
+ RIGHT(REPLICATE('0', 5)
+ SUBSTRING(A_VERSION,
PATINDEX('%[0-9]%', A_VERSION),
LEN(A_VERSION)), 5)
<= RIGHT(SPACE(5)
+ SUBSTRING(B_VERSION,
1,
PATINDEX('%[0-9]%', B_VERSION) - 1), 5)
+ RIGHT(REPLICATE('0', 5)
+ SUBSTRING(B_VERSION,
PATINDEX('%[0-9]%', B_VERSION),
LEN(B_VERSION)) ,5)
如果你要在很多地方做这个操作,你可以考虑为这个操作创建一个函数。
希望对您有所帮助。
非常感谢!它有很大帮助,但是我使用的是 sql 开发人员,我不能将 PATINDEX 与该软件一起使用,我发现等效项是 REGEXP_INSTR,它的工作方式非常相似。
我用这个算法过滤掉 VERSION_B 中字母多于 VERSION_A 的行,然后过滤掉 VERSION_B 大于 [=17= 的行] 当他们有相同数量的字母时:
WHERE
(REGEXP_INSTR(VERSION_B, '[0-9]') < REGEXP_INSTR(VERSION_A, '[0-9]')) OR
(REGEXP_INSTR(VERSION_B, '[0-9]') = REGEXP_INSTR(VERSION_A, '[0-9]') AND VERSION_B <= VERSION_A)