从单个列和单个SQL表中的多个值计算年度百分比
一直在寻找有关“从单个SQL表中单个列中的值计算百分比”的帮助 请允许我给你一点提示(如下所示): 1.)我在SQL2008上的测试环境中工作,需要部署SQL2012上的代码 2.)我使用SQL游标,因为我需要逐行处理结果和数据 3.)我使用查询将这些结果放入一个新表中:从单个列和单个SQL表中的多个值计算年度百分比,sql,sql-server-2008-r2,cursor,percentage,calculation,Sql,Sql Server 2008 R2,Cursor,Percentage,Calculation,一直在寻找有关“从单个SQL表中单个列中的值计算百分比”的帮助 请允许我给你一点提示(如下所示): 1.)我在SQL2008上的测试环境中工作,需要部署SQL2012上的代码 2.)我使用SQL游标,因为我需要逐行处理结果和数据 3.)我使用查询将这些结果放入一个新表中: INSERT INTO tbl_1 (Column_names) SELECT @Column_names_from_cursor_variables 4.)每个id(截至目前)正好有3条记录,如下所示: present
INSERT INTO tbl_1 (Column_names)
SELECT @Column_names_from_cursor_variables
4.)每个id(截至目前)正好有3条记录,如下所示:
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
---------------------------
等等
我需要计算年百分比(同比)以及
每个id区块的QoQ百分比(季度对季度)如下所示:
QoQ --> ((present_year_value-last_quarter_value)/last_quarter_value)*100
YoY --> ((present_year_value-last_year_value)/last_year_value)*100
但是,不知何故,我无法在SQL游标中获得技巧。(使用SQL游标不是强制性的,但我需要逐行计算结果,因此我更喜欢游标)。这可能是一个比您想要的更长的答案,但我想谈谈关于表设置的几个重要问题以及它们的重要性。我的解释会有点倒退,但希望很容易理解 您给出的示例数据可能有点混乱,因为每个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
select *, ROW_NUMBER() over (partition by Id order by YearValue desc) as RN
from Values
您将得到以下结果:
Results
+ -- + ------ + ------- +
| Id | QoQ | YoY |
+ -- + ------ + ------- +
| 1 | 81.81 | 887.6 |
| 2 | 193.22 | 1017.76 |
| 3 | 830.59 | 19.28 |
+ -- + ------ + ------- +
非常简单和直接
但是…
在数据库中进行这样的更改可能并不总是可行的。例如,数据可能不仅仅用于这个问题,以您的格式存储数据可能是最好的。在这种情况下,下面是如何转换数据以获得所需结果的演练
为了使数据表看起来像值表,我们需要在Id内进行显式排序。在这种情况下,我们可以在YearValue字段上下单,但前提是它们是实际日期,而不是字符串。考虑下面的查询:
select Id
, cast((PresentYearValue - LastQuarterValue) as float) / (LastQuarterValue) * 100 as QoQ
, cast((PresentYearValue - LastYearValue) as float) / (LastYearValue) * 100 as YoY
from Values
select *, ROW_NUMBER() over (partition by Id order by YearValue desc) as RN
from Values
这为我们提供了一个类似于数据的表格,但有一个新字段:
Data
+ -- + --------- + -------- + -- +
| Id | YearValue | SalesQty | RN |
+ -- + --------- + -------- + -- +
| 1 | 052017 | 9876 | 1 | -- PresentYearValue
| 1 | 032017 | 5432 | 2 | -- LastQuarterValue
| 1 | 052016 | 1000 | 3 | -- LastYearValue
| 2 | 052017 | 6483 | 1 | -- repeat
| 2 | 032017 | 2211 | 2 |
| 2 | 052016 | 580 | 3 |
| 3 | 052017 | 11316 | 1 |
| 3 | 032017 | 1216 | 2 |
| 3 | 052016 | 9487 | 3 |
+ -- + --------- + -------- + -- +
注意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子句之前添加所需的任何其他字段和into子句。希望这有帮助 这张桌子上的id是什么?(如产品id或与另一个表相关的任何唯一id?)您好,Samanvitha,该id是表中的主键,并且它(准确地)有3条记录,每一条记录有什么问题?你得到的结果中有什么是不正确的?哦,天哪@KindaTechy,我已经阅读了这篇教程的回复,但是从外观上看,我认为这是可行的(尽管我仍然需要尝试整个过程)。请给我一些时间来思考一下这段代码,并进行一些小的修改。我一定会给你回复的。再次感谢你!提前,一切归功于你_KindaTechy@E.Hunt我希望这对你有用。如果没有,请告诉我,也许我们可以找出原因:)是的,它是有效的,在您的逻辑帮助下,我能够修改它,非常感谢您的指导。从你的辛勤工作中学到了很多。@E.Hunt,很高兴听到这个消息。请随意将此标记为答案。