簡體   English   中英

從單個列和單個SQL表中的多個值計算年度百分比

[英]Calculating Yearly Percentage from multiple values from a Single column and in a Single SQL table

一直在尋找有關“根據單個SQL表中單個列中存在的值計算百分比”的幫助。

請讓我給你一點提示(如下):

1.)我正在測試環境中使用SQL2008,需要在SQL2012上部署代碼。

2.)我使用的是SQL游標,因為我需要逐行處理結果並

3.)我使用查詢將這些結果放入新表中:

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塊計算Percentage_YoY(按年)和Percentage_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

您會得到以下結果:

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

這為我們提供了一個類似於Data的表,但帶有一個新字段:

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與(Present,Last)(Quarter,Year)Value之間的對應關系。 我們可以利用這種對應關系將行“透視”為列。

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

從子句前添加你想要的任何其他領域,你條款。 希望這可以幫助!

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM