How to compare software versions using SQL Server?

后端 未结 16 2229
清酒与你
清酒与你 2020-12-03 07:30

When trying to compare software versions 5.12 to 5.8, version 5.12 is newer, however mathematically 5.12 is less than 5.8. How would I compare the two versions so that a new

16条回答
  •  孤城傲影
    2020-12-03 08:18

    You don't say so in the question, but your comment under Tomtom's answer suggests you are storing the version numbers as [decimals][d]. I guess that you have a table like this:

    CREATE TABLE ReleaseHistory (
      VersionNumber DECIMAL(6,3) NOT NULL
    );
    GO
    
    INSERT INTO ReleaseHistory (
      VersionNumber
    )
    VALUES
      (5.12),
      (5.8),
      (12.34),
      (3.14),
      (0.78),
      (1.0);
    GO
    

    The following query is an attempt to rank versions by the order in which they would be released:

    SELECT
      VersionNumber,
      RANK() OVER (ORDER BY VersionNumber) AS ReleaseOrder
    FROM ReleaseHistory;
    

    It produces the following result set:

    VersionNumber                           ReleaseOrder
    --------------------------------------- --------------------
    0.780                                   1
    1.000                                   2
    3.140                                   3
    5.120                                   4
    5.800                                   5
    12.340                                  6
    

    This is not what we expect. Version 5.8 was released before version 5.12!

    Split the version number into its major and minor components to rank the version numbers properly. One way to do this is to convert the decimal value to a string and split on the period. The T-SQL syntax for this is ugly (the language is not designed for string processing):

    WITH VersionStrings AS (
      SELECT CAST(VersionNumber AS VARCHAR(6)) AS VersionString
      FROM ReleaseHistory
    ),
    VersionNumberComponents AS (
      SELECT
        CAST(SUBSTRING(VersionString, 1, CHARINDEX('.', VersionString) - 1) AS INT) AS MajorVersionNumber,
        CAST(SUBSTRING(VersionString, CHARINDEX('.', VersionString) + 1, LEN(VersionString) - CHARINDEX('.', VersionString)) AS INT) AS MinorVersionNumber
      FROM VersionStrings
    )
    SELECT
      CAST(MajorVersionNumber AS VARCHAR(3)) + '.' + CAST(MinorVersionNumber AS VARCHAR(3)) AS VersionString,
      RANK() OVER (ORDER BY MajorVersionNumber, MinorVersionNumber) AS ReleaseOrder
    FROM VersionNumberComponents;
    

    But it provides the expected result:

    VersionString ReleaseOrder
    ------------- --------------------
    0.780         1
    1.0           2
    3.140         3
    5.120         4
    5.800         5
    12.340        6
    

    As Tomtom replied, decimal is a not a good type to store a version number. It would be better to store the version number in two positive integer columns, one containing the major version number and the other containing the minor version number.

提交回复
热议问题