我有一个表,用于存储特定版本软件的兼容性。例如,客户端的版本是否与后端兼容。有一个下限和一个上限,都有主要版本,次要版本和修订版本号。上限数字可以为null(有一个检查约束,确保全部或全部都不为空)。
我想创建一个查询,返回各种majorVersion,minorVersion和revisionVersion数字的行。 示例(clientId省略使其更简单):
minMajorVersion | minMinorVersion | minRevisionVersion | maxMajorVersion | maxMinorVersion | maxRevisionVersion
1 0 0 NULL NULL NULL
1 2 5 NULL NULL NULL
1 3 0 NULL NULL NULL
2 0 1 5 1 0
我想说我想知道哪个客户端版本与后端版本1.2.6兼容。为此,查询应返回前两行,因为最小版本较小,最大版本为NULL。 对于另一个后端版本2.0.1,查询应返回最后一行,对于后端版本5.2.0,查询应该不返回任何内容。
我能够创造的是:
SELECT c.* FROM COMPATIBILITYQUALIFIER q
join client c on (c.id = q.clientid)
WHERE (q.MINBACKENDMAJORVERSION < 2
OR (q.MINBACKENDMAJORVERSION = 2 AND q.MINBACKENDMINORVERSION < 3)
OR (q.MINBACKENDMAJORVERSION = 2 AND q.MINBACKENDMINORVERSION = 3 AND q.MINBACKENDREVISIONVERSION <=6))
AND ((q.MAXBACKENDMAJORVERSION IS NULL)
OR ((q.MAXBACKENDMAJORVERSION > 2)
OR (q.MAXBACKENDMAJORVERSION = 2 AND q.MAXBACKENDMINORVERSION > 3)
OR (q.MAXBACKENDMAJORVERSION = 2 AND q.MAXBACKENDMINORVERSION = 3 AND q.MAXBACKENDREVISIONVERSION >= 6)))
order by c.MAJORVERSION DESC, c.MINORVERSION DESC, c.REVISIONVERSION DESC;
我认为这不会有效果。 一个简单的方法是创建一个存储过程,但我现在不想将代码放入数据库。
有没有办法用子查询来做?还有什么比这更快的吗?
更新。
答案 0 :(得分:0)
当然,查询不是最漂亮的。但仅仅因为你有多个这样的条件子句并不意味着你的查询会变慢。
仅作为可读性问题并避免重复硬编码值,我会将查询重写为以下内容:
select c.*
from compatibilityqualifier q
join (select 2 as major,
3 as minor,
6 as revision
from dual) ver
on 1=1
join client c
on c.id = q.clientid
where ver.major >= q.minBackendMajorVersion
and (ver.major > q.minBackendMajorVersion or ver.minor >= q.minBackendMinorVersion)
and (ver.major > q.minBackendMajorVersion or ver.minor > q.minBackendMinorVersion or ver.revision >= q.minBackendRevisionVersion)
and (q.maxBackendMajorVersion is null
or (ver.major <= q.maxBackendMajorVersion
and (ver.major < q.maxBackendMajorVersion or ver.minor <= q.maxBackendMinorVersion)
and (ver.major < q.maxBackendMajorVersion or ver.minor < q.maxBackendMinorVersion or ver.revision <= q.maxBackendRevisionVersion)
)
)
order by c.majorversion desc,
c.minorversion desc,
c.revisionversion desc
但我希望表现几乎相同。
答案 1 :(得分:0)
对于表示为(Major,Minor,Revision)元组的任何给定版本号,您可以使用以下查询从CompatibilityQualifier表中检索行。例如下面的版本1,2,6:
select q.*
from (select 1 major
, 2 minor
, 6 revision from dual) v
join CompatibilityQualifier q
on ( q.minMajorVersion < v.major or
( q.minMajorVersion = v.major and
( q.minMinorVersion < v.minor or
( q.minMinorVersion = v.minor and
q.minRevisionVersion <= v.revision))))
and ( q.maxMajorVersion is null or
q.maxMajorVersion > v.major or
( q.maxMajorVersion = v.major and
( q.MaxMinorVersion is null or
q.MaxMinorVersion > v.minor or
( q.MaxMinorVersion = v.minor and
( maxRevisionVersion is null or
q.maxRevisionVersion >= v.revision)))));
产生以下结果:
| MINMAJORVERSION | MINMINORVERSION | MINREVISIONVERSION | MAXMAJORVERSION | MAXMINORVERSION | MAXREVISIONVERSION |
|-----------------|-----------------|--------------------|-----------------|-----------------|--------------------|
| 1 | 0 | 0 | (null) | (null) | (null) |
| 1 | 2 | 5 | (null) | (null) | (null) |
对于修订版2,0,1,将返回来自CompatibilityQualifier的每一行,因为在1,x,x记录中没有任何上限。
如果您确实希望在查询的主要版本号与NULL
不同时从结果集中排除maxMajorVersion
值为minMajorVersion
的记录,则可以使用此修订版本:
select q.*
from (select 2 major
, 0 minor
, 1 revision from dual) v
join CompatibilityQualifier q
on ( q.minMajorVersion < v.major or
( q.minMajorVersion = v.major and
( q.minMinorVersion < v.minor or
( q.minMinorVersion = v.minor and
q.minRevisionVersion <= v.revision))))
and ( --q.maxMajorVersion is null or
q.maxMajorVersion > v.major or
( coalesce(q.maxMajorVersion -- When Null compare to minMajorVersion
,q.minMajorVersion) = v.major and
( q.MaxMinorVersion is null or
q.MaxMinorVersion > v.minor or
( q.MaxMinorVersion = v.minor and
( maxRevisionVersion is null or
q.maxRevisionVersion >= v.revision)))));
只返回一行:
| MINMAJORVERSION | MINMINORVERSION | MINREVISIONVERSION | MAXMAJORVERSION | MAXMINORVERSION | MAXREVISIONVERSION |
|-----------------|-----------------|--------------------|-----------------|-----------------|--------------------|
| 2 | 0 | 1 | 5 | 1 | 0 |