如何在SQL中从同一列中划分两个值

时间:2013-03-14 03:05:21

标签: sql sql-server sql-server-2008-r2

正如标题所述,我想将两个值彼此分开,这两个值在同一列中。 E.g。

    A             B              C            D
  Shirts         2011           85            0
  Shirts         2012           92      percent change from 2011 to 2012
  Shirts         2013          100      percent change from 2012 to 2013
  Pants          2011           31            0
  Pants          2012           42      percent change from 2011 to 2012
  Pants          2013           55      percent change from 2012 to 2013
  Jacket         2011           10            0
  Jacket         2012           16      percent change from 2011 to 2012
  Jacket         2013           18      percent change from 2012 to 2013

在此示例中,列D将从C列派生,其中2012的值从2011中减去,然后乘以100得到百分比。

我不知道如何设置查询我尝试做了一堆子查询,但不知道如何将它们链接在一起。任何帮助将不胜感激。

7 个答案:

答案 0 :(得分:2)

您可以通过自我加入来完成此任务:

SELECT curr.ClothingType, curr.SalesYear, curr.NumberSold
   , COALESCE((CAST((curr.NumberSold - prev.NumberSold) AS NUMERIC(5,2)) / prev.NumberSold) * 100, 0) AS PercentChange
FROM #Clothes AS curr
LEFT JOIN #Clothes AS prev ON curr.ClothingType = prev.ClothingType
   AND curr.SalesYear = prev.SalesYear + 1

SQL Fiddle Example

答案 1 :(得分:1)

我同意Shivan,但仅仅因为我不知道如何在没有PHP的情况下做到这一点。使用PHP,只需要拉出两个总数,进行数学运算并回答问题。

还请务必阅读本文,因为它是更重要的部分 你的数学错了。 (Shirts2011 - Shirts2012) * 100并未向您提供百分比变化。它只是给你100 times the difference of the two(实际上,基于你的措辞的负面差异)。数学方面,你想要的是:

((Item2012-Item2011)/Item2011)*100

我知道外面的parens不是必需的,但它们使它更容易阅读。百分比变化与两者与初始差异的比率的100倍相同。

编辑添加PHP代码。

PHP看起来很糟糕,但它完成了工作。

$conn = new PDO(HOST:DATABASE, USERNAME, PASSWORD);
    $query = "SELECT A, B, C FROM yourTable";
    $st = $conn->prepare($query);
    $st->execute();

$list = array();
while($row = $st->fetch(PDO::FETCH_ASSOC))
    $list[] = $row;

$fill = array();
for($i=1; $i<count($list); $i++)
    if($list[$i]['A'] == $list[$i-1][A])
        $fill[] = $array('A' => $list[$i]['A'],
                         'B' => $list[$i]['B'],
                         'D' => ($list[$i]['C']-$list[$i-1]['C'])/$list[$i-1]['C']*100);

$update = new PDO(HOST:DATABASE, USERNAME, PASSWORD);
    for($i=0; $i<count($fill); $i++){
        $query = "UPDATE yourTable SET D = " . $fill[$i]['D'] . " WHERE A = " . $fill[$i]['A'] . " AND B = " . $fill[$i]['B'];
        $st = $update->prepare($query);
        $st->execute();
    }

只需初始化您的表格,其中2011 D列= 0。

UPDATE yourTable SET D = 0 WHERE B = 2011;

在火焰开始之前,我知道一个foreach会起作用;我只是认为看起来更好的标准(并允许你跳过2011年的第一个值)。

答案 2 :(得分:1)

如果我正确理解您的要求,您可以使用递归cte来完成结果。这使用ROW_NUMBER()和分区(分组)列A.

如果你不能保证B列的连续年份,这种方法最有效。如果你总是有连续的年份,那么bobs提供了最好的选择。

with cte as (
  select A, B, C, 
    ROW_NUMBER() OVER (PARTITION BY A ORDER BY B) rn
  from yourtable
  ),
recursive_cte as (
  select A, B, C, 0 prc
  from cte
  where rn = 1
  union all
  select y.A, y.B, y.C, y.C-c.C prc
  from cte y 
    join cte c on y.a=c.a and y.rn=c.rn+1
)
select * 
from recursive_cte
order by a, b

SQL Fiddle Demo

这将返回每年与前一组按A列分组的差异。为简单起见,它使用第二个CTE。如果您希望更改实际百分比,请更新上面的公式。

- 修改

由于听起来您正在寻找百分比增长,请尝试使用此公式替换y.C-c.C prc:

cast(y.C as decimal(10,2))/cast(c.C as decimal(10,2))

如果您的数据类型是整数,请使用CAST

答案 3 :(得分:1)

这是一个获得你所追求的选项

SELECT t1.a, t1.b, t1.c,
    CASE WHEN t2.c IS NULL THEN 0 ELSE t1.c - t2.c END AS d,
    CASE WHEN t2.c IS NULL THEN 0 ELSE (1.0 * t1.c - t2.c) / t1.c * 100.0 END AS pct
FROM t t1
LEFT OUTER JOIN t t2 ON t1.a = t2.a
    AND t1.b = t2.b + 1

SQL Fiddle Example

答案 4 :(得分:0)

试试这个:

SELECT t1.type A, t1.year B, t1.value C,
IF(
  EXISTS(
    SELECT 1 FROM table t2 WHERE t1.type = t2.type AND t1.year = (t2.year - 1)
  ),
  ((SELECT t3.year FROM table t3 WHERE t1.type = t3.type AND t1.year = (t3.year - 1)) - t1.year)/t1.year,
  0
) D
FROM table t1

效率不高,但可以做到。

答案 5 :(得分:0)

试试这个:

select Y2013.*, Y2012.C, Y2013.C, Y2013.C/Y2011.C
from (
  select * from data where B = year(getdate())
) Y2013
left join (
  select * from data where B = year(getdate()) - 1
) Y2012 on Y2012.A = Y2013.A
left join (
  select * from data where B = year(getdate()) - 2
) Y2011 on Y2011.A = Y2012.A
 and  Y2011.A = Y2013.A

答案 6 :(得分:0)

你也可以试试这个:

UPDATE mytable t1
  INNER JOIN mytable t2 
  ON t1.A = t2.A AND t2.B = t1.B - 1
SET t1.D = ((t1.C - t2.C)  / t2.C) * 100;

请参阅fiddle

假设你已经有0作为D的默认值。如果没有,只需在运行此查询之前将所有行设置为0。