Mysql рассчитать рост на основе кварталов - PullRequest
0 голосов
/ 27 октября 2018

У меня есть база данных с двумя таблицами - компании и отчеты .Я хочу рассчитать изменение с q1 (квартал 1) до q2 (квартал 2).Я попытался использовать (следующий) подзапрос, но тогда основной запрос не удался ...

FROM
    (SELECT revenue FROM reports WHERE quarter = 'q2' AND fiscal_year = 2018) AS q,
    (SELECT revenue FROM reports WHERE quarter = 'q1' AND fiscal_year = 2017) AS lq

Вот БД Fiddle, чтобы помочь вам понять проблему и схему:

https://www.db -fiddle.com / f / eE8SNRojn45h7Rc1rPCEVN / 4

Текущий простой запрос.

SELECT 
    c.name, r.quarter, r.fiscal_year, r.revenue, r.taxes, r.employees
FROM 
    companies c
JOIN
    reports r 
ON
    r.company_id = c.id
WHERE
    c.is_marked = 1;

Ожидаемые результаты (это то, что мне нужно):

+---------+----------+----------------+----------+--------------+-----------+------------------+
|  Name   | Revenue  | Revenue_change |  Taxes   | Taxes_change | Employees | Employees_change |
+---------+----------+----------------+----------+--------------+-----------+------------------+
| ABC INC |    11056 | +54.77         | 35000.86 | -28.57%      |       568 | -32              |
| XYZ INC |     5000 | null           | null     | null         |        10 | +5               |
+---------+----------+----------------+----------+--------------+-----------+------------------+

Буду очень признателен за помощь в создании этого запроса.Заранее спасибо.

Ответы [ 6 ]

0 голосов
/ 05 ноября 2018

Это дало мне вывод, что вам нужно.

select 
    c.name, 
    r2.revenue, 
     concat(TRUNCATE(100 * (r2.revenue - r1.revenue) / r2.revenue,2),"%") as revenue_change,
    r2.taxes, 
   concat(TRUNCATE( 100 * (r2.taxes - r1.taxes) / r2.taxes,2),"%")  as taxes_change,
    r2.employees, 
    r2.employees - r1.employees as employees_change
from 
    companies c
    LEFT JOIN reports r1 ON (c.id = r1.company_id and r1.quarter = 'q1') 
    LEFT JOIN reports r2 ON (c.id = r2.company_id and r2.quarter = 'q2') 

Вывод:

Спасибо !!!

0 голосов
/ 01 ноября 2018

Я попробовал. Вот как бы я это сделал.

SELECT 
  c.name, 
  reportsQ2.quarter, 
  reportsQ2.revenue as revenu1, 
  reportsQ1.revenue as revenue2, 
  (COALESCE(reportsQ2.revenue, 0) - COALESCE(reportsQ1.revenue, 0)) as difference
FROM 
    reports as reportsQ2 
LEFT JOIN 
    reports as reportsQ1 ON reportsQ1.company_id = reportsQ2.company_id
AND 
    reportsQ1.quarter = 'Q1'
LEFT JOIN
    companies as c ON c.id = reportsQ2.company_id
WHERE 
    reportsQ2.quarter = 'Q2'

Итак, сначала я выбрал все отчеты за второй квартал. Затем я присоединился к первому кварталу с тем же идентификатором компании.

На данный момент у вас уже есть вся необходимая информация для перехода к вычислениям. Я использовал COALESCE(), чтобы убедиться, что нулевые значения не мешают вычислениям, чтобы вывести нулевое значение вместо действительного числа.

Наконец, я присоединился к таблице companies, чтобы получить имена.

Я сделал математику со строками доходов и вывел их как difference.

Надеюсь, это поможет!

0 голосов
/ 30 октября 2018

Я предоставлю вам свой подход к этому, используя только одно объединение с группировкой по предложению и агрегатными функциями .Последний шаг вычисления pecentajes выполняется с использованием производной таблицы из первого подхода:

SELECT
    der.name, der.quarter, der.fiscal_year,
    der.revenue,
    100 * der.revenue_change / der.revenue AS revenue_change,
    der.taxes,
    100 * der.taxes_change / der.taxes AS taxes_change,
    der.employees,
    der.employees_change
FROM
(
    /* First approach (with raw changes) */
    SELECT
        c.name,
        MAX(r.quarter) AS quarter,
        ANY_VALUE(r.fiscal_year) AS fiscal_year,
        SUM(CASE WHEN r.quarter = "Q2" THEN r.revenue END) AS revenue,
        IF (COUNT(r.revenue) = 2,
            SUM(CASE WHEN r.quarter = "Q1" THEN (-1 * r.revenue) ELSE r.revenue END),
            NULL) AS revenue_change,
        SUM(CASE WHEN r.quarter = "Q2" THEN r.taxes END) AS taxes,
        IF (COUNT(r.taxes) = 2,
            SUM(CASE WHEN r.quarter = "Q1" THEN (-1 * r.taxes) ELSE r.taxes END),
            NULL) AS taxes_change,
        SUM(CASE WHEN r.quarter = "Q2" THEN r.employees END) AS employees,
        IF (COUNT(r.employees) = 2,
            SUM(CASE WHEN r.quarter = "Q1" THEN (-1 * r.employees) ELSE r.employees END),
            NULL) AS employees_change
    FROM
        companies AS c
    LEFT JOIN
        reports AS r ON r.company_id = c.id AND r.quarter IN ("Q1","Q2")
    GROUP BY
        c.id
) AS der

Вы можете проверить прогрессию к окончательному запросу по следующей ссылке:

https://www.db -fiddle.com / f / 2tUC1gGJusVnXSyGhHGWc / 3


Обобщение запроса

Я обобщил предыдущий запрос дляПодходя к сравнению кварталов из другого финансового года, как вы спросили в комментариях, вот как я это сделаю:

SET @q1Year = 2017;
SET @q2Year = 2018;
SET @q1 = "Q1" COLLATE utf8mb4_unicode_ci;
SET @q2 = "Q2" COLLATE utf8mb4_unicode_ci;

SELECT
    der.name,
    der.compared_quarters,
    der.quarter,
    der.fiscal_year,
    der.revenue,
    100 * der.revenue_change / der.revenue AS revenue_change,
    der.taxes,
    100 * der.taxes_change / der.taxes AS taxes_change,
    der.employees,
    der.employees_change
FROM                                                       
(
    /* This query generate raw changes on revenue, taxes and employees */
    SELECT
        c.name,
        CONCAT(@q1,"-",@q1Year," vs ",@q2,"-",@q2Year) AS compared_quarters,
        @q2 AS quarter,
        @q2Year AS fiscal_year,
        SUM(IF(r.quarter = @q2, r.revenue, 0)) AS revenue,
        IF (COUNT(r.revenue) = 2,
            SUM(IF(r.quarter = @q1, -1 * r.revenue, r.revenue)),
            NULL) AS revenue_change,
        SUM(IF(r.quarter = @q2, r.taxes, 0)) AS taxes,
        IF (COUNT(r.taxes) = 2,
            SUM(IF(r.quarter = @q1, -1 * r.taxes, r.taxes)),
            NULL) AS taxes_change,
        SUM(IF(r.quarter = @q2, r.employees, 0)) AS employees,
        IF (COUNT(r.employees) = 2,
            SUM(IF(r.quarter = @q1, -1 * r.employees, r.employees)),
            NULL) AS employees_change
    FROM
        companies AS c
    LEFT JOIN
        reports AS r ON r.company_id = c.id
    AND
        ((r.quarter = @q1 AND r.fiscal_year = @q1Year) OR (r.quarter = @q2 AND r.fiscal_year = @q2Year))
    GROUP BY
        c.id
) AS der;

Вы можете проверить пример по следующей ссылке:

https://www.db -fiddle.com / ж / 2tUC1gGJusVnXSyGhHGWc / 4

0 голосов
/ 30 октября 2018

Использование оконных функций MySQL 8.0:

WITH cte AS (
  SELECT c.name, quarter, fiscal_year
   ,revenue,100*(revenue-LAG(revenue) OVER s)/NULLIF(revenue,0) AS change_revenue
   ,taxes,100*(taxes-LAG(taxes) OVER s)/NULLIF(taxes,0) AS change_taxes
   ,employees,employees-LAG(employees) OVER s AS change_employees
  FROM companies c
  JOIN reports r ON r.company_id = c.id
  WINDOW s AS (PARTITION BY r.company_id ORDER BY fiscal_year, quarter)
)
SELECT *
FROM cte
WHERE quarter = 'Q2';  -- only to get specific quarter
-- comment this condition to get quarter to quarter comparison 

db <> Fiddle demo

0 голосов
/ 29 октября 2018

Вы можете сделать это простым SQL, если вам нужно сравнить только две четверти. Программирование не требуется.
Подзапросов нет, просто присоединяйте компании к отчетам дважды по кварталу.

select 
    c.name, 
    r2.revenue, 
    100 * (r2.revenue - r1.revenue) / r2.revenue as revenue_change,
    r2.taxes, 
    100 * (r2.taxes - r1.taxes) / r2.taxes as taxes_change,
    r2.employees, 
    r2.employees - r1.employees as employees_change
from 
    companies c
    LEFT JOIN reports r1 ON (c.id = r1.company_id and r1.quarter = 'q1')
    LEFT JOIN reports r2 ON (c.id = r2.company_id and r2.quarter = 'q2')

См. https://www.db -fiddle.com / f / 6hwbPofSwAiqGBPFZWKxhi / 0

0 голосов
/ 27 октября 2018

Очень сложно получить результат, используя чистый SQL.Но я делаю это.

Выполните следующие sql.Я надеюсь, что вы получите помощь с этим SQL.

select 
    qd2.name as Name,
    qd2.Revenue as Revenue,
    qd2.Revenue - qd1.Revenue as Revenue_Change,
    qd2.Taxes as Taxes,
    (qd2.Taxes - qd1.Taxes) * 100 / qd1.Taxes as Taxes_Change,
    qd2.Employees as Employees,
    (qd2.Employees - qd1.Employees) as Employees_Change
from 
    (
        SELECT 
            (@cnt := @cnt + 1) AS rowNumber, 
            c.name as name, 
            r.revenue as Revenue,
            r.taxes as Taxes,
            r.employees as Employees
        FROM 
            companies c
        JOIN
            reports r 
        CROSS JOIN (SELECT @cnt := 0) AS dummy
        ON
            r.company_id = c.id and
            r.quarter = "q2"
        order by name
    ) as qd2
    JOIN
    (
        SELECT 
            (@cnt2 := @cnt2 + 1) AS rowNumber, 
            c.name as name, 
            r.revenue as Revenue,
            r.taxes as Taxes,
            r.employees as Employees
        FROM 
            companies c
        JOIN
            reports r 
        CROSS JOIN (SELECT @cnt2 := 0) AS dummy
        ON
            r.company_id = c.id and
            r.quarter = "q1"
        order by name
    ) as qd1
    ON qd1.rowNumber = qd2.rowNumber

Результаты следующие

Name    Revenue Taxes   Employees   Revenue_Change  Taxes_Change    Employees_Change
ABC INC 11056   35000.86    568 6056    -22.221798  -32
XYZ LLC 5000    null    10  null    null    5
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...