根据指定值对数据进行排序

时间:2017-05-04 10:23:53

标签: sql sql-server sorting tsql

我有一张表Containers,其中包含以下数据:

Name         | CapacityNormal | CapacityMax
-------------+----------------+------------
Container #1 |              2 |           2
Container #2 |              2 |           3
Container #3 |              2 |           4
Container #4 |              3 |           4
Container #5 |              3 |           5

变量Quantity。我想按顺序对数量的容器进行排序:

  • 容量正​​常大于/等于数量的容器
  • 容量最大值大于/等于数量的容器
  • 其他一切

请注意:

  • 不希望浪费正常的插槽
  • 超出正常容量会导致死亡

牢记以上几点必须根据这些规则打破关系:

  • 浪费正常容量的容器
  • 惩罚最小的容器

如果Quantity = 3,预期输出将为:

Name         | CapacityNormal | CapacityMax | Comment
-------------+----------------+-------------+-------------------------------------------
Container #4 |              3 |           4 | wastes 0 slots
Container #5 |              3 |           5 | wastes 1 slot
Container #2 |              2 |           3 | exceeds normal capacity, incurs 1 penalty
Container #3 |              2 |           4 | exceeds normal capacity, incurs 2 penalty
Container #1 |              2 |           2 | container cannot be used

换句话说,我想为不超过正常容量或产生最小罚款的工作选择最佳容器。这是样本数据和测试:

WITH Containers(Name, CapacityNormal, CapacityMax) AS (
    SELECT 'Container #1', 2, 2 UNION
    SELECT 'Container #2', 2, 3 UNION
    SELECT 'Container #3', 2, 4 UNION
    SELECT 'Container #4', 3, 4 UNION
    SELECT 'Container #5', 3, 5
), Tests(Quantity) AS (
    SELECT 1 UNION 
    SELECT 2 UNION 
    SELECT 3 UNION 
    SELECT 4 UNION 
    SELECT 5 UNION
    SELECT 6
)
SELECT CONCAT(Name, ' (', CapacityNormal, '/', CapacityMax, ')') AS Container, Quantity
FROM Containers
CROSS JOIN Tests
ORDER BY Quantity /* sort criteria goes here */

2 个答案:

答案 0 :(得分:1)

您可以像这样使用订单

;WITH Containers(Name, CapacityNormal, CapacityMax) AS (
   SELECT 'Container #1', 2, 2 UNION
   SELECT 'Container #2', 2, 3 UNION
   SELECT 'Container #3', 2, 4 UNION
   SELECT 'Container #4', 3, 4 UNION
   SELECT 'Container #5', 3, 5 UNION 
   SELECT 'Container #6', 4, 5
), Tests(Quantity) AS (
   SELECT 1 UNION 
   SELECT 2 UNION 
   SELECT 3 UNION 
   SELECT 4 UNION 
   SELECT 5 UNION
   SELECT 6
)
SELECT *
FROM Containers c
CROSS JOIN Tests t
ORDER BY Quantity,
       CASE WHEN c.CapacityNormal >= t.Quantity THEN 0 ELSE 1 END,
       CASE WHEN c.CapacityMax >= t.Quantity THEN 0 ELSE 1 END,     
       abs(c.CapacityNormal- quantity) ,
       abs(c.CapacityMax - quantity)  

注意:按CASE WHEN c.CapacityNormal >= t.Quantity THEN 0 ELSE 1 END, CASE WHEN c.CapacityMax >= t.Quantity THEN 0 ELSE 1 END排序相当于

  • 容量正​​常大于/等于数量的容器
  • 容量最大值大于/等于数量的容器

然后按abs(c.CapacityNormal- quantity) , abs(c.CapacityMax - quantity)排序

  • 具有最小浪费的正常容量容器的容器
  • 最小刑罚

答案 1 :(得分:0)

你可以使用这样的语句:

order by 
    case 
        when capacitynormal >= quantity then 1
        when capacitymax >= quantity then 2
        else 3
    end,
    case 
        when capacitynormal >= quantity then capacitynormal - quantity
        else 9999 --set this to a number bigger than any capacity normal
    end,
    capacitymax - quantity

请注意,我也为第二个元素使用了case语句,因为我认为你的问题意味着如果你已超出正常容量,你想在仲裁逻辑中忽略它。