比较SQL查询中的版本号

时间:2015-09-22 17:04:18

标签: sql oracle

我有一个表,用于存储特定版本软件的兼容性。例如,客户端的版本是否与后端兼容。有一个下限和一个上限,都有主要版本,次要版本和修订版本号。上限数字可以为null(有一个检查约束,确保全部或全部都不为空)。

definition of the table

我想创建一个查询,返回各种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; 

我认为这不会有效果。 一个简单的方法是创建一个存储过程,但我现在不想将代码放入数据库。

有没有办法用子查询来做?还有什么比这更快的吗?

更新。

2 个答案:

答案 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 |