对数字范围mysql执行计算

时间:2014-12-21 00:54:42

标签: mysql sql select pivot range

是否有可能在MySQL中使用数字范围,如果是这样,那么最好的方法是完成以下操作。

  1. 我有两个表格列的范围。
  2. +------+-------+--------+
    | Col1 | Col2  | Action |
    +------+-------+--------+
    | 1    | 100   | Add    |
    +------+-------+--------+
    
    1. 接下来,我希望减去范围[60,65],减去范围[20,40]并添加范围[200,210]。所以我将这些记录添加到我的表中。
    2. +------+-------+--------+
      | Col1 | Col2  | Action |
      +------+-------+--------+
      | 1    | 100   | Add    |
      | 60   | 65    | Subtr  |
      | 20   | 40    | Subtr  |
      | 200  | 210   | Add    |
      +------+-------+--------+
      
      1. 最后,我想检索剩下的范围。查询应返回类似的内容。
      2. +------+-------+
        | Col1 | Col2  |
        +------+-------+
        | 1    | 19    |
        | 41   | 59    |
        | 66   | 100   |
        | 200  | 210   |
        +------+-------+
        

        额外信息

        • 业务逻辑可防止重叠范围
        • 业务逻辑可防止减去可用范围内的范围

2 个答案:

答案 0 :(得分:1)

试试这个:

SELECT (CASE WHEN Action1 = 'Add' THEN col1 
             WHEN Action1 = 'Subtr' THEN col1 + 1 
             ELSE 0 
        END) col1, 
       (CASE WHEN Action2 = 'Add' THEN col2 
             WHEN Action2 = 'Subtr' THEN col2 - 1 
             ELSE 0 
        END) col2
FROM (SELECT CEILING(RowNum / 2) AS RowId, 
             MAX(CASE WHEN RowNum % 2 = 1 THEN col ELSE 0 END) AS col1, 
             MAX(CASE WHEN RowNum % 2 = 1 THEN Action ELSE '' END) AS Action1,         
             MAX(CASE WHEN RowNum % 2 = 0 THEN col ELSE 0 END) AS col2, 
             MAX(CASE WHEN RowNum % 2 = 0 THEN Action ELSE '' END) AS Action2
      FROM (SELECT (@id:=@id+1) AS RowNum, col, Action 
            FROM (SELECT col1 AS col, Action 
                  FROM tableA 
                  UNION 
                  SELECT col2 AS col, Action 
                  FROM tableA 
                 ) AS A, 
                 (SELECT @id:=0) AS B
            ORDER BY col
           ) AS A
      GROUP BY RowId
     ) AS A;

选中此SQL FIDDLE DEMO

<强>输出

| COL1 | COL2 |
|------|------|
|    1 |   19 |
|   41 |   59 |
|   66 |  100 |
|  200 |  210 |

<强> ::说明::

正如您在我的查询中看到的那样,我首先在单列中使用其操作类型获取了所有起始范围和结束范围,然后为每个记录提供行号以将该数据转换为两列,因为我想要创建内表如下:

| ROWID | COL1 | ACTION1 | COL2 | ACTION2 |
|-------|------|---------|------|---------|
|     1 |    1 |     Add |   20 |   Subtr |
|     2 |   40 |   Subtr |   60 |   Subtr |
|     3 |   65 |   Subtr |  100 |     Add |
|     4 |  200 |     Add |  210 |     Add |

最后我使用CASE语句生成特定输出。

答案 1 :(得分:0)

MySql没有专门处理此功能的任何功能。最简单,最有效的方法是创建存储过程。创建一个游标来迭代Col1,Col2,Action表中的行(让我们调用action表)。然后保留一个临时表来保存当前的范围集。对于substract命令,您可以生成另一个游标,该游标仅获取需要更新的tmp表中的行。例如:

select * from tmpResults where (action.col1 <= tmpResults.col1 <= action.col2)
or (action.col1 <= tmpResults.col2 <=  action.col2)

然后删除应用的行并添加要添加的一行或两行。

添加行时,我假设您可以重叠,但不能重复?

无论如何,使用存储过程是我推荐的方法。