2015-09-22 6 views
1

У меня есть таблица, которая используется для хранения совместимости для определенной версии программного обеспечения. Например, совместима ли версия клиента с бэкэнд. Существует нижняя и верхняя граница, у обоих есть номера основных, второстепенных и версий версий. Номера с верхней границей могут быть нулевыми (существует контрольное ограничение, которое гарантирует, что либо все, либо ни одно из них не равно нулю).Сравнение номеров версий в запросе SQL

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; 

Я не думаю, что это будет производительным. Простым способом сделать это будет создание хранимой процедуры, но я не хочу сейчас вводить код в базу данных.

Есть ли способ сделать это с помощью подзапросов? Что-нибудь еще, что быстро?

ОБНОВЛЕНО.

+3

Без фактической таблицы + определения данных + запросы, которые вы пробовали, трудно дать правильный ответ. – sstan

+0

Ваши требования не ясны. Просьба предоставить образцы данных и лучшее описание проблемы, которую вы пытаетесь решить. – Sentinel

+0

@sstan Спасибо, вы оба правы. жаль, что я немного устал, когда задал вопрос. Теперь я обновил его, пожалуйста, взгляните еще раз. –

ответ

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 

Но я ожидаю, что производительность будет в значительной степени идентичны.

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 | 
+0

Примечание. Чтобы запрос не возвращал строки версии 1, если запрошенные версии являются версиями 2.0.1 или 5.2.0, для таблицы CompatibilityQualifier должен быть жесткий максимум 2.0.0 или ниже для каждого из 1 .xx или более мягкий максимум 1.null.null, такой как 1.10.265 или 1.30.null. – Sentinel

Смежные вопросы