2017-05-30 37 views
0

一直在寻找一些关于“根据单个SQL表中单列中的值计算百分比”的帮助。计算单列和单个SQL表中多个值的年度百分比

请允许我给你一点点抬头(如下):

1)我在我的测试环境是在SQL2008工作,并需要部署代码是SQL2012。

2)我使用的是SQL游标,因为我需要的结果行由行处理和

3)这些结果我现在用的查询将进入一个新的表:

INSERT INTO tbl_1 (Column_names) 
SELECT @Column_names_from_cursor_variables 

4)有(截至目前)正好3记录每个ID为:

present_year_value (say,MAY2017), 
last_quarter_value (say,MAR2017) 
last_year_value (say,MAY2016) 

如下:

id  yearValue salesQty 
----------------------------- 
1  052017  9876  
1  032017  5432  
1  052016  1000  
---------------------------  
2  052017  9876  
2  032017  5432  
2  052016  1000  
---------------------------  
3  052017  9876  
3  032017  5432  
3  052016  1000  
--------------------------- 

等等...

我需要计算Percentage_YoY(年同比),以及 Percentage_QoQ(较上一季度)为ID的每个块为:

QoQ --> ((present_year_value-last_quarter_value)/last_quarter_value)*100 

YoY --> ((present_year_value-last_year_value)/last_year_value)*100 

但是,不知何故,我无法获得SQL游标中的技巧。 (使用SQL游标不是强制性的,但我需要逐行计算结果,因此我更愿意使用Cursor)。

+0

此表中的id是什么? (如产品编号或相关的另一张表?任何唯一的ID) –

+0

你好Samanvitha,该ID是在表的主键,它已(完全一致)3记录每个 –

+0

问题是什么?你得到的结果是不正确的? – nscheaffer

回答

0

这可能是比您想要的更长的答案,但我想解决几个关于您的表格设置以及它们为什么重要的重要内容。我的解释会稍微有些落后,但希望它会很容易遵循。

你给可以是一个有点混乱,因为它是每个ID都是一样的,所以我要改变他们有点像这样的例子数据:

Data 
+ -- + --------- + -------- + 
| Id | YearValue | SalesQty | 
+ -- + --------- + -------- + 
| 1 | 052017 | 9876  | 
| 1 | 032017 | 5432  | 
| 1 | 052016 | 1000  | 
| 2 | 052017 | 6483  | 
| 2 | 032017 | 2211  | 
| 2 | 052016 | 580  | 
| 3 | 052017 | 11316 | 
| 3 | 032017 | 1216  | 
| 3 | 052016 | 9487  | 
+ -- + --------- + -------- + 

开始,如果您的表看起来像这样,而不是答案应该是显而易见:

Values 
+ -- + ----------- + ---------------- + ---------------- + ------------- + 
| Id | CurrentDate | PresentYearValue | LastQuarterValue | LastYearValue | 
+ -- + ----------- + ---------------- + ---------------- + ------------- + 
| 1 | 052017  | 9876    | 5432    | 1000   | 
| 2 | 052017  | 6483    | 2211    | 580   | 
| 3 | 052017  | 11316   | 1216    | 9487   | 
+ -- + ----------- + ---------------- + ---------------- + ------------- + 

然后,假设你的数据类型为SalesQty字段不是一个小数,您可以使用下面的查询:

select Id 
     , cast((PresentYearValue - LastQuarterValue) as float)/(LastQuarterValue) * 100 as QoQ 
     , cast((PresentYearValue - LastYearValue) as float)/(LastYearValue) * 100 as YoY 
    from Values 

,你会得到以下结果:

Results 
+ -- + ------ + ------- + 
| Id | QoQ | YoY  | 
+ -- + ------ + ------- + 
| 1 | 81.81 | 887.6 | 
| 2 | 193.22 | 1017.76 | 
| 3 | 830.59 | 19.28 | 
+ -- + ------ + ------- + 

非常简单明了。

但是...

它可能并不总是做出这样的改变你的数据库是可行的。例如,数据可能不仅仅用于这一个单一的问题,而且以您的格式存储它可能是最好的整体。在这种情况下,这是一个演示如何转换数据以获得您想要的结果。

为了使我们的数据表看起来像我们的值表,我们需要一个明确的在Id的内部排序。在这种情况下,我们可以在YearValue字段上订购,但如果它们是实际日期而不是字符串,则只能订购。考虑下面的查询:

select *, ROW_NUMBER() over (partition by Id order by YearValue desc) as RN 
    from Values 

这给了我们类似的数据,但一个新的字段的表:

​​

通知RN和(目前,最后)(季,年)值之间的对应关系。我们可以利用这种对应关系将这些行“转”为列。

select a.Id 
     , case RN when 1 then a.YearValue end as CurrentDate 
     , case RN when 1 then a.SalesQty end as PresentYearValue 
     , case RN when 2 then a.SalesQty end as LastQuarterValue 
     , case RN when 3 then a.SalesQty end as LastYearValue 
     , a.RN as RN 
    from (
     select *, ROW_NUMBER() over (partition by id order by SalesQty desc) as RN 
      from #Values 
    ) a 

这让我们像

+ -- + ----------- + ---------------- + ---------------- + ------------- + -- + 
| Id | CurrentDate | PresentYearValue | LastQuarterValue | LastYearValue | RN | 
+ -- + ----------- + ---------------- + ---------------- + ------------- + -- + 
| 1 | 2017-05-01 | 9876    | NULL    | NULL   | 1 | 
| 1 | 2017-05-01 | NULL    | 5432    | NULL   | 2 | 
| 1 | 2017-05-01 | NULL    | NULL    | 1000   | 3 | 
| 2 | 2017-05-01 | 6483    | NULL    | NULL   | 1 | 
| 2 | 2017-05-01 | NULL    | 2211    | NULL   | 2 | 
| 2 | 2017-05-01 | NULL    | NULL    | 580   | 3 | 
| 3 | 2017-05-01 | 11316   | NULL    | NULL   | 1 | 
| 3 | 2017-05-01 | NULL    | 9487    | NULL   | 2 | 
| 3 | 2017-05-01 | NULL    | NULL    | 1216   | 3 | 
+ -- + ----------- + ---------------- + ---------------- + ------------- + -- + 

表一快速分组,我们可以收起该表格。

select a.Id 
     , max(case RN when 1 then a.YearValue end) as CurrentDate 
     , max(case RN when 1 then a.SalesQty end) as PresentYearValue 
     , max(case RN when 2 then a.SalesQty end) as LastQuarterValue 
     , max(case RN when 3 then a.SalesQty end) as LastYearValue 
    from (
     select *, ROW_NUMBER() over (partition by id order by YearValue desc) as RN 
      from Data 
    ) a 
    group by a.Id 

,这为我们提供了准确的值表:

Values 
+ -- + ----------- + ---------------- + ---------------- + ------------- + 
| Id | CurrentDate | PresentYearValue | LastQuarterValue | LastYearValue | 
+ -- + ----------- + ---------------- + ---------------- + ------------- + 
| 1 | 052017  | 9876    | 5432    | 1000   | 
| 2 | 052017  | 6483    | 2211    | 580   | 
| 3 | 052017  | 11316   | 1216    | 9487   | 
+ -- + ----------- + ---------------- + ---------------- + ------------- + 

最后,掖最后查询到的CTE,并与第一查询结合起来,以获得您想要的值:

; with 
    Values as (
     select a.Id 
       , max(case RN when 1 then a.YearValue end) as CurrentDate 
       , max(case RN when 1 then a.SalesQty end) as PresentYearValue 
       , max(case RN when 2 then a.SalesQty end) as LastQuarterValue 
       , max(case RN when 3 then a.SalesQty end) as LastYearValue 
      from (
       select *, ROW_NUMBER() over (partition by id order by YearValue desc) as RN 
        from Data 
      ) a 
      group by a.Id 
    ) 
select Id 
     , cast((PresentYearValue - LastQuarterValue) as float)/(LastQuarterValue) * 100 as QoQ 
     , cast((PresentYearValue - LastYearValue) as float)/(LastYearValue) * 100 as YoY 
    from Values 

在from子句之前,将所需的任何其他字段和添加到子句中。希望这可以帮助!

+0

Ohh Gosh @KindaTechy,我已经阅读过这篇教程的种类回复,但从外观上看,我认为这可以工作(尽管如此,我仍然需要尝试这一切)。请给我一些时间来反思这个代码,并尝试做一些小的改动。一定会回到你身边。再一次,谢谢!提前#allCreditToYou_KindaTechy –

+0

@ E.Hunt我希望这对你的作品。让我知道,如果不是这样,也许我们可以找出原因:) – KindaTechy

+0

是它的工作原理,我能与你的逻辑的帮助下对其进行修改和一个大感谢你指导我。从你的这份辛勤工作中学到很多东西。 –