SQL манипулирование таблицей (агрегирование и группировка) - PullRequest
0 голосов
/ 23 декабря 2019

Я хотел бы сделать ежедневный запрос (используя bigquery), чтобы сравнить суммы для различных метрик между вчера и сегодня. Пример набора данных выглядит следующим образом:
enter image description here

при условии, что сегодня 23 декабря 2019 года, запрос агрегирует различные показатели (доход, стоимость, прибыль) для разных клиентов за 23 декабря(сегодня) и 22 декабря (вчера), если сумма (вчера) / сумма (сегодня) не находится в пределах 0,5-1,5, то она будет помечена как аномальная

, запрос будетсделано ежедневно, и новый результат будет просто добавлен. в идеале финальная таблица должна выглядеть следующим образом:

enter image description here Моя главная задача состоит в том, чтобы я мог сделать это только для одного показателя (т. е. дохода), но не уверенкак применить ко всем метрикам (а также сделать запрос более эффективным). это код, который я написал

SELECT cust_id,

SUM(CASE WHEN date = DATE_ADD(CURRENT_DATE(), INTERVAL -1 DAY) 
         THEN revenue
    END) AS sum(yesterday),

SUM(CASE WHEN date = DATE_ADD(CURRENT_DATE(), INTERVAL 0 DAY)
         THEN revenue
    END) AS sum(today),

SUM(CASE WHEN date = DATE_ADD(CURRENT_DATE(), INTERVAL -1 DAY) 
         THEN revenue
    END) / SUM(CASE WHEN date = DATE_ADD(CURRENT_DATE(), INTERVAL 0 DAY)
         THEN revenue
    END) as ratio,

FROM `dataset`
GROUP BY cust_id

, и код дает мне:
enter image description here

Заранее извиняюсь за отсутствие ясности ввопрос, так как я новичок в этом и не уверен, как точнее сформулировать этот вопрос

Ответы [ 3 ]

1 голос
/ 23 декабря 2019

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

однако, если вы хотите придерживаться SQL, вам необходимо сначала отключить строки, поместив каждую меру в отдельную строку, а затем сгруппировать промежуточные результаты, например:

WITH unpivoted AS
(
    SELECT
        date
      , 'revenue'       AS metrics
      , SUM( revenue )  AS amount
      , cust_id
    FROM
        `dataset`
    GROUP
    BY
        date
      , cust_id

    UNION ALL

    SELECT
        date
      , 'cost'          AS metrics
      , SUM( cost )     AS amount
      , cust_id
    FROM
        `dataset`
    GROUP
    BY
        date
      , cust_id
    -- add more desired metrics
)
SELECT
    date as date_generated
  , cust_id
  , metrics
  , SUM( CASE WHEN date = DATE_ADD( CURRENT_DATE() , INTERVAL  0 DAY ) THEN amount END ) AS today
  , SUM( CASE WHEN date = DATE_ADD( CURRENT_DATE() , INTERVAL -1 DAY ) THEN amount END ) AS yesterday
    ...

FROM
    unpivoted
WHERE
    date >= DATE_ADD(CURRENT_DATE(), INTERVAL -1 DAY ) 
AND date <= DATE_ADD(CURRENT_DATE(), INTERVAL  0 DAY ) 

GROUP
BY
    date, cust_id, metrics
0 голосов
/ 31 декабря 2019

Вы можете сначала отключить столбцы, а затем сгруппировать результаты. После этого вам может понадобиться использовать LAG () для отображения данных за один день и за предыдущий в одной строке.

WITH unpivoted AS
(
  SELECT
    date,
    'revenue' AS metrics,
    SUM( revenue ) AS amount,
    cust_id
  FROM
    `dataset`
  GROUP BY
    date, metrics, cust_id

UNION ALL

  SELECT
    date,
    'cost' AS metrics,
    SUM( cost ) AS amount,
    cust_id
  FROM
    `dataset`
  GROUP BY
    date, metrics, cust_id

UNION ALL

  SELECT
    date,
    'profit' AS metrics,
    SUM( profit ) AS amount,
    cust_id
  FROM
    `dataset`
  GROUP BY
    date, metrics, cust_id
)

SELECT
  date as date_generated,
  metrics,
  cust_id,
  LAG(SUM( amount )) OVER (PARTITION BY cust_id, metrics ORDER BY date) yesterday,
  SUM( amount ) AS today,
  LAG(SUM( amount )) OVER (PARTITION BY cust_id, metrics ORDER BY date) / SUM(amount) as ratio,
  CASE WHEN LAG(SUM( amount )) OVER (PARTITION BY cust_id, metrics ORDER BY date) / SUM(amount)<0.5 then 'TRUE' 
      WHEN LAG(SUM( amount )) OVER (PARTITION BY cust_id, metrics ORDER BY date) / SUM(amount)>1.5 then 'TRUE'
      WHEN LAG(SUM( amount )) OVER (PARTITION BY cust_id, metrics ORDER BY date) / SUM(amount) is NULL then 'TRUE'
      ELSE 'FALSE'
  END as anomalous

FROM
  unpivoted

WHERE date >= DATE_ADD(CURRENT_DATE(), INTERVAL -1 DAY ) AND date <= DATE_ADD(CURRENT_DATE(), INTERVAL  0 DAY )    

GROUP BY 
  date_generated, cust_id, metrics

ORDER BY 
  date_generated, metrics, cust_id

Обратите внимание, что мое решение ограничивается только текущим днем ​​и предыдущим днем ​​(сегодня и вчера) при использовании предложения WHERE, поэтому его можно использовать для агрегирования показателей за более чем два дня.

0 голосов
/ 23 декабря 2019

Вы можете суммировать данные и затем использовать lag() или join для ввода данных за предыдущие дни:

with t as (
      select cust_id, date,
             sum(revenue) as revenue,
             sum(cost) as cost,
             sum(profit) as profit
      from dataset
      where date >= date_add(current_date, interval -1 day)
      group by cust_id, date
     )
select t.cust_id,
       today, yesterday
from t today left join
     t yesterday
     on yesterday.cust_id = today.cust_id and
        yesterday.date = date_add(current_date, interval -1 day)
where today.date = current_date;
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...