SUM агрегация с порогом по двум таблицам в bigquery - PullRequest
0 голосов
/ 20 июня 2019

В следующей таблице показано часовое энергопотребление устройств:

+--------------+-----------+-----------------------+
| energy_usage | device_id |  timestamp            |
+--------------+-----------+-----------------------+
| 10           | 1         |  2019-02-12T01:00:00  |
| 16           | 2         |  2019-02-12T01:00:00  |
| 26           | 1         |  2019-03-12T02:00:00  |
| 24           | 2         |  2019-03-12T02:00:00  |
+--------------+-----------+-----------------------+

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

+--------------+------------------+--------------------+-----------+------------+
| energy_usage | energy_usage_day | energy_usage_night | device_id |    date    |
+--------------+------------------+--------------------+-----------+------------+
| 80           | 30               | 50                 | 1         | 2019-06-02 |
| 130          | 60               | 70                 | 2         | 2019-06-03 |
+--------------+------------------+--------------------+-----------+------------+

Меня интересует только использование энергии выше определенного порога.Следующий запрос работает для меня:

WITH temp AS (
  SELECT *, SUM(usage) OVER(win) > 50 qualified,
    SUM(usage) OVER(win) - 50 rolling_sum,
    EXTRACT(HOUR FROM timestamp) BETWEEN 8 AND 19 day_hour,
    EXTRACT(MONTH FROM timestamp) month,
    FORMAT_TIMESTAMP("%Y-%m-%d", timestamp) date
  FROM `project.dataset.table`
  WINDOW win AS (PARTITION BY device_id, TIMESTAMP_TRUNC(timestamp, MONTH) ORDER BY timestamp)
), temp_with_adjustments AS (
  SELECT *, 
    IF(
      ROW_NUMBER() OVER(PARTITION BY device_id, MONTH ORDER BY timestamp) = 1, 
      rolling_sum, 
      usage
    ) AS adjusted_energy_usage
  FROM temp 
  WHERE qualified
)
SELECT ROUND(SUM(adjusted_energy_usage), 4) energy_usage,
  ROUND(SUM(IF(day_hour, adjusted_energy_usage, 0)), 4) energy_usage_day,
  ROUND(SUM(IF(NOT day_hour, adjusted_energy_usage, 0)), 4) energy_usage_night,
  device_id,
  date
FROM temp_with_adjustments
GROUP BY device_id, date

Хотя в первой таблице показано потребление энергии, у меня есть другая таблица, в которой показан соответствующий счет за использование:

+--------------+-----------+-----------------------+
| usage_charge | device_id |  timestamp            |
+--------------+-----------+-----------------------+
| 0.2          | 1         |  2019-02-12T01:00:00  |
| 0.6          | 2         |  2019-02-12T01:00:00  |
| 0.1          | 1         |  2019-03-12T02:00:00  |
| 1.2          | 2         |  2019-03-12T02:00:00  |
+--------------+-----------+-----------------------+

Я хочу получитьпонимание затрат на использование в дневное и ночное время по устройствам и датам для устройств, которые потребляют энергию> 50. Результаты могут выглядеть следующим образом:

+--------------+------------------+--------------------+--------------+------------------+--------------------+-----------+------------+
| energy_usage | energy_usage_day | energy_usage_night | usage_charge | usage_charge_day | usage_charge_night | device_id |    date    |
+--------------+------------------+--------------------+--------------+------------------+--------------------+-----------+------------+
| 80           | 30               | 50                 | 1.2          | 0.4              | 0.8                | 1         | 2019-06-02 |
| 130          | 60               | 70                 | 2.5          | 1                | 1.5                | 2         | 2019-06-03 |
+--------------+------------------+--------------------+--------------+------------------+--------------------+-----------+------------+

Поэтому моей первой мыслью было использование точно такого же запроса для использованияобвинения, как я сделал для использования энергии.Однако, хотя пороговое значение 50 работает для потребления энергии, я не могу назвать фиксированный порог для платы за использование, поскольку расчет платы зависит от устройства.Поэтому я должен сначала получить потребление энергии> 50 и использовать временные метки для агрегирования сборов за использование.Любые идеи, как я мог бы сделать это в Bigquery?Это вообще возможно?

1 Ответ

1 голос
/ 20 июня 2019

Ниже приведено описание BigQuery Standard SQL, и оно основано только на применении шаблона, который я вижу в первоначальном запросе, поэтому мне сложно на 100% быть уверенным, что это именно то, что вам нужно. Но в любом случае, это, безусловно, хорошее начало здесь

#standardSQL
WITH temp AS (
  SELECT *, SUM(IF(qualified, usage_charge, 0)) OVER(win) rolling_charge
  FROM (
    SELECT *, SUM(usage) OVER(win) > 50 qualified,
      SUM(usage) OVER(win) - 50 rolling_sum,
      EXTRACT(HOUR FROM timestamp) BETWEEN 8 AND 19 day_hour,
      EXTRACT(MONTH FROM timestamp) month,
      FORMAT_TIMESTAMP("%Y-%m-%d", timestamp) date
    FROM `project.dataset.usage`
    JOIN `project.dataset.charges` USING(device_id, timestamp)
    WINDOW win AS (PARTITION BY device_id, TIMESTAMP_TRUNC(timestamp, MONTH) ORDER BY timestamp)
  )
  WINDOW win AS (PARTITION BY device_id, TIMESTAMP_TRUNC(timestamp, MONTH) ORDER BY timestamp)
), temp_with_adjustments AS (
  SELECT *, 
    IF(
      ROW_NUMBER() OVER(PARTITION BY device_id, MONTH ORDER BY timestamp) = 1, 
      rolling_sum, 
      usage
    ) AS adjusted_energy_usage
  FROM temp 
  WHERE qualified
)
SELECT ROUND(SUM(adjusted_energy_usage), 4) energy_usage,
  ROUND(SUM(IF(day_hour, adjusted_energy_usage, 0)), 4) energy_usage_day,
  ROUND(SUM(IF(NOT day_hour, adjusted_energy_usage, 0)), 4) energy_usage_night,
  ROUND(SUM(rolling_charge), 4) usage_charge,
  ROUND(SUM(IF(day_hour, rolling_charge, 0)), 4) usage_charge_day,
  ROUND(SUM(IF(NOT day_hour, rolling_charge, 0)), 4) usage_charge_night,
  device_id,
  date
FROM temp_with_adjustments
GROUP BY device_id, date
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...