1

Given:

+-----------+---------------+-------------+-------+
|   Name    |   Item        | Year        | Value |
+-----------+---------------+-------------+-------+
| Company A | Sales         | 2017        |   100 |
| Company A | Sales         | 2016        |   100 |
| Company A | Sales         | 2015        |   400 |
| Company A | Profit        | 2017        |    50 |
| Company A | Profit        | 2016        |    50 |
| Company A | Profit        | 2015        |   200 |
| Company B | Sales         | 2017        |   200 |
| Company B | Sales         | 2016        |   100 |
| Company B | Profit        | 2017        |    20 |
| Company B | Profit        | 2016        |    20 |
+-----------+---------------+-------------+-------+

How do I use SQL to transform it to:

+----------+---------------+--------+-----------+
|   Name   |   Year        | Margins| 2 yr Ave  |
+----------+---------------+--------+-----------+
| CompanyA | 2015          |    50% |    NULL   |  
| CompanyA | 2016          |    50% |    50%    |  
| CompanyA | 2017          |    50% |    50%    |  
| CompanyB | 2016          |    20% |    NULL   |
| CompanyB | 2017          |    10% |    15%    |
+----------+---------------+--------+-----------+

and

+----------+---------------+--------+-----------+
|   Name   |   Year        | CompA  | CompB     |
+----------+---------------+--------+-----------+
| Margin   | 2015          |    50% |    NULL   |  
| Margin   | 2016          |    50% |    20%    |  
| Margin   | 2017          |    50% |    10%    |  
| 2Yr Ave  | 2015          |   NULL |    NULL   |
| 2Yr Ave  | 2016          |    50% |    NULL   |
| 2Yr Ave  | 2017          |    50% |    15%    |
+----------+---------------+--------+-----------+
  • Margin: (profit/sales*100) of a given year and
  • 2 Year Ave: Margin this year + Margin of previous year / 2, NULL if there is no data for previous year.
marc_s
  • 732,580
  • 175
  • 1,330
  • 1,459
Marc
  • 23
  • 4

2 Answers2

6

My approach would be to first aggregate once over your table using GROUP BY to compute the profit margins for each company in each year. Then, make a second pass using LAG() to calculate the recent two year margin average.

WITH cte AS (
    SELECT
        Name,
        Year,
        100*MAX(CASE WHEN Item = 'Profit' THEN Value END) /
            MAX(CASE WHEN Item = 'Sales' THEN Value END) AS Margins
    FROM yourTable
    GROUP BY
        Name,
        Year
)

SELECT
    Name,
    Year,
    Margins,
    (Margins + LAG(Margins) OVER (PARTITION BY Name ORDER BY Year)) / 2 AS [2 yr Avg]
FROM cte
ORDER BY
    Name,
    Year

For your second table output, you can just pivot the result from this query. Place the code I gave you into a CTE, and then pivot on the margin columns.

Output:

enter image description here

Demo here:

Rextester

Tim Biegeleisen
  • 502,043
  • 27
  • 286
  • 360
0

As at this point you didn't include any attempt on your side, I'll just post an idea to show you one possible approach.

SELECT T1.Name, T1.Year, Margins = 100 * T2.Value / T1.Value
FROM TBL1 T1
INNER JOIN TBL1 T2 ON T1.Name = T2.Name AND T1.Year = T2.Year AND T1.Item = 'Sales' AND T2.Item = 'Profit'
GROUP BY T1.Name, T1.Year

What I'm doing is joining the table in order to have the values you need in the same row, so you can then easily do the calculation.

This way you get the first result table without the average. Then I would use this result as a source for a second query to calculate the average, also joining the table with itself.

Your second result table is the same thing as the first one but transposed. If you search for that you will find plenty of information, like in here.

Andrew
  • 7,602
  • 2
  • 34
  • 42