What’s the problem? Say you have a version number such as 1.2.3 stored in a MySql database as a varchar, and you want to sort this version number. Without any decimals, here is the sorting descending:
+———+
| version |
+———+
| 9960 |
| 9952 |
| 9765 |
| 9764 |
| 10011 |
+———+
5 rows in set (0.00 sec)
It thinks 9960 > 10011
If you don’t have a decimal point this can be easily remedied by doing:
ORDER BY CAST(version AS UNSIGNED) DESC
But as soon as you put a decimal into the version, it ignores everything to the right of the decimal point.
My solution is a PHP sorting algorithm.
$versions is an indexed array that has this format, which could easily come from a database
array
  0 => 
    array
      ’id’ => int 88
      ’version’ => 
        array
          0 => int 0
          1 => int 9
          2 => int 10011
  1 => 
    array
      ’id’ => int 87
      ’version’ => 
        array
          0 => int 0
          1 => int 9
          2 => int 9960

// convert all values to ints
array_walk_recursive($versions, function(&$val, $i)
{
    if (is_string($val))
        $val = (int)$val;
});
// make to arrays the same length by padding them with 0s
function normalize($a, $b)
{
    $al = count($a);
    $bl = count($b);
    if ($al < $bl)
    {
        // add 0s to $a until they are the same size
        while (count($a) < $bl)
            $a[] = 0;
    }
    elseif ($al > $bl)
    {
        // add 0s to $b until they are the same size
        while ($al > count($b))
            $b[] = 0;
    }
    return array($a, $b);
}
//compare to integers and decide which one is bigger
// return 0 if they are equal
function check($a, $b)
{
    if ($a < $b)
        return 1;
    elseif ($a > $b)
        return -1;
    else
        return 0;
}
// sort the array
usort($versions, function($a, $b)
{
    // make sure the major_version arrays have the same length, pad with 0s to correct
    list($a['version'], $b['version']) = normalize($a['version'], $b['version']);
    for ($i=0; $i < count($a['version']); $i++)
        $check = check($a['version'][$i], $b['version'][$i]);
    return $check;
});
  • Share/Bookmark