Соединение SQL с четвертичным периодом (периоды от 4 до 3 месяцев) - PullRequest
2 голосов
/ 24 июня 2019

Предположим, мы измерили появление черепах три раза в год в тертилях (три 4-месячных периода). Затем мы перешли на кварталы (четыре 3-месячных периода). Я хотел бы сравнить значения текущего года с предыдущим годом.

Редактировать благодаря комментариям Стива. Первоначально я использовал неправильное слово для 4-месячного периода, называя его триместр . Правильное слово для 4-месячного периода: тертиль или квадриместр .

+------+--------+------------+------------+----------+
| year | period |     d1     |     d2     | value_cy |
+------+--------+------------+------------+----------+
| 2018 | T1     | 2018-01-01 | 2018-04-01 |       10 |
| 2018 | T2     | 2018-05-01 | 2018-08-01 |       20 |
| 2018 | T3     | 2018-09-01 | 2018-12-01 |       30 |
| 2019 | Q1     | 2019-01-01 | 2019-03-01 |       18 |
| 2019 | Q2     | 2019-04-01 | 2019-06-01 |       16 |
| 2019 | Q3     | 2019-07-01 | 2019-09-01 |       14 |
| 2019 | Q4     | 2019-10-01 | 2019-12-01 |       12 |
+------+--------+------------+------------+----------+

и это желаемые результаты:

+------+--------+------------+------------+----------+----------+
| year | period |     d1     |     d2     | value_cy | value_py |
+------+--------+------------+------------+----------+----------+
| 2018 | T1     | 2018-01-01 | 2018-04-01 |       10 |          |
| 2018 | T2     | 2018-05-01 | 2018-08-01 |       20 |          |
| 2018 | T3     | 2018-09-01 | 2018-12-01 |       30 |          |
| 2019 | Q1     | 2019-01-01 | 2019-03-01 |       18 |      7.5 |
| 2019 | Q2     | 2019-04-01 | 2019-06-01 |       16 |     12.5 |
| 2019 | Q3     | 2019-07-01 | 2019-09-01 |       14 |     17.5 |
| 2019 | Q4     | 2019-10-01 | 2019-12-01 |       12 |     22.5 |
+------+--------+------------+------------+----------+----------+
where
    Q1=3/4 * T1
    Q2=1/4 * T1 + 1/2 * T2 

Мои усилия:

Идея, которая приходит мне в голову, - это промежуточная таблица, которая переводит период с триместров на месяцы, а затем на кварталы.

+--------+-------+
| period | month |
+--------+-------+
| Q1     |     1 |
| Q1     |     2 |
| Q1     |     3 |
| Q2     |     4 |
| Q2     |     5 |
| Q2     |     6 |
| Q3     |     7 |
| Q3     |     8 |
| Q3     |     9 |
| Q4     |    10 |
| Q4     |    11 |
| Q4     |    12 |
| T1     |     1 |
| T1     |     2 |
| T1     |     3 |
| T1     |     4 |
| T2     |     5 |
| T2     |     6 |
| T2     |     7 |
| T2     |     8 |
| T3     |     9 |
| T3     |    10 |
| T3     |    11 |
| T3     |    12 |
+--------+-------+

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

1 Ответ

0 голосов
/ 24 июня 2019

Предполагая, что вы не хотите продолжать запись данных в триместрах в будущем (т. Е. Это можно решить с помощью одноразовой операции), и что вы работаете с SQL Server, вы можете предварительно обрабатывать данные за триместр в квартал данные в той же таблице, чтобы облегчить сравнение. Что-то вроде следующего даст вам ваши значения Q1 и Q2:

-- Q1 rows
INSERT INTO data_table (year, period, d1, d2, value_cy)
SELECT year, period, d1, d2, t1_component.value_cy FROM
(
    SELECT
        year,
        'Q1' AS period,
        CONCAT(year, '-01-01') AS d1,
        CONCAT(year, '-04-01') AS d2,
    FROM
        data_table
) main
CROSS APPLY
(
    SELECT 0.75 * value_cy AS value_cy
    FROM data_table
    WHERE year = main.year
    AND period = 'T1'
) t1_component;

-- Q2 rows
INSERT INTO data_table (year, period, d1, d2, value_cy)
SELECT year, period, d1, d2, t1_component.value_cy + t2_component.value_cy FROM
(
    SELECT
        year,
        'Q2' AS period,
        CONCAT(year, '-05-01') AS d1,
        CONCAT(year, '-08-01') AS d2,
    FROM
        data_table
) main
CROSS APPLY
(
    SELECT 0.25 * value_cy AS value_cy
    FROM data_table
    WHERE year = main.year
    AND period = 'T1'
) t1_component
CROSS APPLY
(
    SELECT 0.5 * value_cy AS value_cy
    FROM data_table
    WHERE year = main.year
    AND period = 'T2'
) t2_component;

Вы можете получить значения Q3 и Q4, настроив вышеуказанные запросы по мере необходимости. После того, как вы получите все значения в квартальном формате, вы можете выполнить самостоятельное СОЕДИНЕНИЕ, чтобы получить результаты предыдущего года наряду с результатами текущего года, хотя это будет медленно из-за необходимости ПРИСОЕДИНЯТЬСЯ к рассчитанному значению (хотя это может удовлетворить ваши потребности) :

SELECT
    cy.year,
    cy.period,
    cy.d1,
    cy.d2,
    cy.value_cy,
    py.value_cy AS value_py
FROM data_table cy
INNER JOIN data_table py
    ON py.year-1 = cy.year
WHERE cy.period IN ('Q1', 'Q2', 'Q3', 'Q4')

Кроме того, вы можете взглянуть на оператор PIVOT , который в основном преобразует значение строки в заголовке столбца:

 SELECT period, [2019], [2018]
 FROM
     (SELECT period, year, value_cy FROM data_table WHERE period IN ('Q1', 'Q2', 'Q3', 'Q4')) AS src
 PIVOT
     (value_cy FOR year IN ([2019], [2018])
 AS pivotTable
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...