Расчет на разных строках в пределах одного столбца в SQL - PullRequest
0 голосов
/ 04 февраля 2019

У меня есть таблица со следующей информацией, я использую Google BigQuery.Я пытаюсь агрегировать по person_ID в соответствии с несколькими различными типами вычислений, количеством дней между средним и начальным, конечным и начальным, а также близким и начальным.

|Person_ID|Action |Date       |
|100      |Initial|22/12/2018 |
|100      |Middle |23/12/2018 |
|100      |End    |29/12/2018 |
|100      |Close  |31/12/2018 |
|150      |Initial|02/01/2019 |
|150      |Middle |04/01/2019 |
|150      |End    |07/01/2019 |
|150      |Close  |10/01/2019 |

Я пытаюсь завершитьв итоге получу следующий результат:

|Person_ID|Middle_Minus_initial|End_Minus_initial|Close_Minus_initial|
|100      |         1          |         7       |          9        |
|150      |         2          |         5       |          8        |

Я не совсем уверен, как это сделать вообще, поскольку я довольно новичок, когда дело доходит до SQL, поэтому любая помощь будет оценена.Спасибо.

Ответы [ 3 ]

0 голосов
/ 04 февраля 2019

Другой вариант, который позволяет избежать использования агрегации, - это присоединение к нескольким подзапросам, например:

SELECT
    t.personid, 
    DATEDIFF(tm.date, ti.date, day) Middle_Minus_initial,
    DATEDIFF(te.date, ti.date, day) End_Minus_initial,
    DATEDIFF(tc.date, ti.date, day) Close_Minus_initial 
FROM 
    (SELECT DISTINCT personid FROM mytable) t
    LEFT JOIN mytable ti ON ti.personid = t.personid  AND ti.action = 'Initial'
    LEFT JOIN mytable tm ON tm.personid = t.personid AND tm.action = 'Middle'
    LEFT JOIN mytable te ON te.personid = t.personid AND te.action = 'End'  
    LEFT JOIN mytable tc ON tc.personid = t.personid AND tc.action = 'Close'    
0 голосов
/ 04 февраля 2019

Ниже для BigQuery Standard SQL

#standardSQL
SELECT Person_ID,
  DATE_DIFF(Middle, Initial, DAY) AS Middle_Minus_initial,
  DATE_DIFF(`End`, Initial, DAY) AS End_Minus_initial,
  DATE_DIFF(Close, Initial, DAY) AS Close_Minus_initial
FROM (
  SELECT Person_ID, 
    PARSE_DATE('%d/%m/%Y', MAX(IF(Action = 'Initial', `Date`, NULL))) AS Initial, 
    PARSE_DATE('%d/%m/%Y', MAX(IF(Action = 'Middle', `Date`, NULL))) AS Middle, 
    PARSE_DATE('%d/%m/%Y', MAX(IF(Action = 'End', `Date`, NULL))) AS `End`, 
    PARSE_DATE('%d/%m/%Y', MAX(IF(Action = 'Close', `Date`, NULL))) AS Close
  FROM `project.dataset.table`
  GROUP BY Person_ID
)

Вы можете протестировать, поиграть с выше, используя примеры данных из вашего вопроса, как в примере ниже

#standardSQL
WITH `project.dataset.table` AS (
  SELECT 100 Person_ID, 'Initial' Action, '22/12/2018' `Date` UNION ALL 
  SELECT 100, 'Middle', '23/12/2018' UNION ALL 
  SELECT 100, 'End', '29/12/2018' UNION ALL 
  SELECT 100, 'Close', '31/12/2018' UNION ALL 
  SELECT 150, 'Initial', '02/01/2019' UNION ALL 
  SELECT 150, 'Middle', '04/01/2019' UNION ALL 
  SELECT 150, 'End', '07/01/2019' UNION ALL 
  SELECT 150, 'Close', '10/01/2019' 
)
SELECT Person_ID,
  DATE_DIFF(Middle, Initial, DAY) AS Middle_Minus_initial,
  DATE_DIFF(`End`, Initial, DAY) AS End_Minus_initial,
  DATE_DIFF(Close, Initial, DAY) AS Close_Minus_initial
FROM (
  SELECT Person_ID, 
    PARSE_DATE('%d/%m/%Y', MAX(IF(Action = 'Initial', `Date`, NULL))) AS Initial, 
    PARSE_DATE('%d/%m/%Y', MAX(IF(Action = 'Middle', `Date`, NULL))) AS Middle, 
    PARSE_DATE('%d/%m/%Y', MAX(IF(Action = 'End', `Date`, NULL))) AS `End`, 
    PARSE_DATE('%d/%m/%Y', MAX(IF(Action = 'Close', `Date`, NULL))) AS Close
  FROM `project.dataset.table`
  GROUP BY Person_ID
)
-- ORDER BY Person_ID

с результатом

Row Person_ID   Middle_Minus_initial    End_Minus_initial   Close_Minus_initial  
1   100         1                       7                   9    
2   150         2                       5                   8    
0 голосов
/ 04 февраля 2019

Один метод условного агрегирования:

select person_id,
       date_diff(max(case when action = 'Middle' then date end),
                 max(case when action = 'Initial' then date end),
                 day) as middle_minus_initial,
       date_diff(max(case when action = 'End' then date end),
                 max(case when action = 'Initial' then date end),
                 day) as end_minus_initial,
       date_diff(max(case when action = 'Close' then date end),
                 max(case when action = 'Initial' then date end),
                 day) as close_minus_initial
from t
group by person_id;
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...