正面和负面价值的交替

时间:2015-08-29 10:44:33

标签: sql sql-server

谢谢你的关注。 我有一个名为“PROD_COST”的表,有5个字段

(ID,Duration,Cost,COST_NEXT,COST_CHANGE). 

我需要额外的字段称为“组”进行聚合。

  • 持续时间=价格有效的天数(1天= 1row)。
  • 成本=当天的产品价格。
  • Cost_next =潜在客户(成本,1,0)。
  • Cost_change = Cost_next - 费用。

现在我需要按Cost_change进行分组。有可能 正,负或0值。

+----+---+------+------+------+
|  1 | 1 | 10   | 8,5  | -1,5 |
|  2 | 1 | 8,5  | 12,2 | 3,7  |
|  3 | 1 | 12,2 | 5,3  | -6,9 |
|  4 | 1 | 5,3  | 4,2  | 1,2  |
|  5 | 1 | 4,2  | 6,2  | 2    |
|  6 | 1 | 6,2  | 9,2  | 3    |
|  7 | 1 | 9,2  | 7,5  | -2,7 |
|  8 | 1 | 7,5  | 6,2  | -1,3 |
|  9 | 1 | 6,2  | 6,3  | 0,1  |
| 10 | 1 | 6,3  | 7,2  | 0,9  |
| 11 | 1 | 7,2  | 7,5  | 0,3  |
| 12 | 1 | 7,5  | 0    | 7,5  |
+----+---+------+------+------+`

我需要进行查询,该查询将按照第一个负值或正值(+ - + - + - )对其进行分组。最后一个字段是我想要的。 对不起我的英文`

+----+---+------+------+------+---+
|  1 | 1 | 10   | 8,5  | -1,5 | 1 |
|  2 | 1 | 8,5  | 12,2 | 3,7  | 2 |
|  3 | 1 | 12,2 | 5,3  | -6,9 | 3 |
|  4 | 1 | 5,3  | 4,2  | 1,2  | 4 |
|  5 | 1 | 4,2  | 6,2  | 2    | 4 |
|  6 | 1 | 6,2  | 9,2  | 3    | 4 |
|  7 | 1 | 9,2  | 7,5  | -2,7 | 5 |
|  8 | 1 | 7,5  | 6,2  | -1,3 | 5 |
|  9 | 1 | 6,2  | 6,3  | 0,1  | 6 |
| 10 | 1 | 6,3  | 7,2  | 0,9  | 6 |
| 11 | 1 | 7,2  | 7,5  | 0,3  | 6 |
| 12 | 1 | 7,5  | 0    | 7,5  | 6 |
+----+---+------+------+------+---+`

2 个答案:

答案 0 :(得分:0)

如果您在SQL Server 2012中,可以使用窗口函数执行此操作:

select 
  id, COST_CHANGE, sum(GRP) over (order by id asc) +1
from
(
  select
    *,
    case when sign(COST_CHANGE) != sign(isnull(lag(COST_CHANGE) 
      over (order by id asc),COST_CHANGE)) then 1 else 0 end as GRP
  from
    PROD_COST
) X

Lag将从前一行获取值,检查它的符号并将其与当前行进行比较。如果值不匹配,则大小写将返回1.外部选择将执行这些数字的运行总计,并且每次有1时,它将增加总数。

也可以在旧版本中使用相同的逻辑,您只需要使用id从表中获取前一行,并通过重新计算当前行之前的所有行来执行总计。< / p>

SQL Fiddle

中的示例

答案 1 :(得分:0)

詹姆斯的答案很接近,但它没有正确处理零值。这是一个非常简单的修改。一个棘手的近似值使用了产品变化之间的差异:

select id, COST_CHANGE, sum(IsNewGroup) over (order by id asc) +1
from (select pc.*,
             (case when sign(cost_change) - sign(lag(cost_change) over (order by id)) between -1 and 1
                   then 0
                   else 1 -- `NULL` intentionally goes here
              end) IsNewGroup
      from Prod_Cost
     ) pc

为清楚起见,here是一个零值的SQL小提琴。根据我对这个问题的理解,OP只希望实际改变符号。

这可能仍然不正确。 OP根本不清楚如何处理0值。