BigQuery 在选择不同行时按一个字段中的最大值分组
BigQuery group by maximum value in one field while selecting distinct rows
对于每 20 分钟的时间间隔,我试图找到带宽的最大值(下面 table 中的 mbps
列),每个唯一的 IP 地址生成,与相应的端口号。
每个 IP 地址在每 20 分钟内可能会或不会出现超过一次。每次在 20 分钟的时间间隔内记录一个 IP 地址时,列出的端口号可能相同也可能不同。
例如下面table中,ip地址192.168.10.1在12:20中出现了3次,端口号分别为443、80、80。在另一种情况下,IP 地址 192.168.10.2 在 12:40 期间出现两次,相同的端口号 443,列出两次,但 mbps(带宽)列的值不同。
目标是 select 并且只列出每个唯一的 IP 地址一次,对于每个二十分钟的时间段,按 mbps 降序排列。
table根据数据注入的时间进行分区。
我打算编写一个 cron 作业来自动执行此查询。 cron 作业将 运行 每小时,每周 7 天。查询将采用标准 SQL.
原table:
Row time ip_address port mbps
1 01/01/2019 12:20 192.168.10.1 443 100
2 01/01/2019 12:20 192.168.10.1 80 120
3 01/01/2019 12:20 192.168.10.2 80 200
4 01/01/2019 12:20 192.168.10.1 80 110
5 01/01/2019 12:40 192.168.10.2 443 200
6 01/01/2019 12:40 192.168.10.3 443 300
7 01/01/2019 12:40 192.168.10.2 443 200
8 01/01/2019 12:40 192.168.10.1 443 300
9 01/01/2019 13:00 192.168.10.3 443 90
10 01/01/2019 13:00 192.168.10.2 80 100
11 01/01/2019 13:00 192.168.10.1 443 500
执行下面的代码,
#standardSQL
SELECT
FORMAT_TIMESTAMP("%d/%m/%Y %H:%M", TIMESTAMP_SECONDS, 'Europe/London') AS time,
ip_address,
port,
SUM(bandwidth) AS mbps,
FROM
dataset1.table1
WHERE
_PARTITIONDATE = DATE_SUB(CURRENT_DATE(),INTERVAL 0 DAY)
AND timestamp > TIMESTAMP_ADD(CURRENT_TIMESTAMP(),INTERVAL -40 MINUTE)
GROUP BY
time,
ip_address,
port
ORDER BY
time,
mbps DESC
我明白了 table,
Row time ip_address port mbps
1 01/01/2019 12:20 192.168.10.2 80 200
2 01/01/2019 12:20 192.168.10.1 80 120
3 01/01/2019 12:20 192.168.10.1 80 110
4 01/01/2019 12:20 192.168.10.1 443 100
5 01/01/2019 12:40 192.168.10.1 443 300
6 01/01/2019 12:40 192.168.10.3 443 300
7 01/01/2019 12:40 192.168.10.2 25 200
8 01/01/2019 12:40 192.168.10.2 443 160
9 01/01/2019 13:00 192.168.10.1 443 500
10 01/01/2019 13:00 192.168.10.2 80 100
11 01/01/2019 13:00 192.168.10.3 443 90
这不是我想要的。相反,我想要这个:
Row time ip_address port mbps
1 01/01/2019 12:20 192.168.10.2 80 200
2 01/01/2019 12:20 192.168.10.1 80 120
3 01/01/2019 12:40 192.168.10.1 443 300
4 01/01/2019 12:40 192.168.10.3 443 300
5 01/01/2019 12:40 192.168.10.2 25 200
6 01/01/2019 13:00 192.168.10.1 443 500
7 01/01/2019 13:00 192.168.10.2 80 100
8 01/01/2019 13:00 192.168.10.3 443 90
我做错了什么?
以下适用于 BigQuery 标准 SQL
#standardSQL
SELECT time, ip_address,
ARRAY_AGG(STRUCT(port, mbps) ORDER BY mbps DESC LIMIT 1)[OFFSET(0)].*
FROM `project.dataset.table`
GROUP BY time, ip_address
您可以使用您问题中的示例数据来测试和使用上面的示例,如下例所示
#standardSQL
WITH `project.dataset.table` AS (
SELECT '01/01/2019 12:20' time, '192.168.10.1' ip_address, 443 port, 100 mbps UNION ALL
SELECT '01/01/2019 12:20', '192.168.10.1', 80, 120 UNION ALL
SELECT '01/01/2019 12:20', '192.168.10.2', 80, 200 UNION ALL
SELECT '01/01/2019 12:20', '192.168.10.1', 80, 110 UNION ALL
SELECT '01/01/2019 12:40', '192.168.10.2', 443, 200 UNION ALL
SELECT '01/01/2019 12:40', '192.168.10.3', 443, 300 UNION ALL
SELECT '01/01/2019 12:40', '192.168.10.2', 443, 200 UNION ALL
SELECT '01/01/2019 12:40', '192.168.10.1', 443, 300 UNION ALL
SELECT '01/01/2019 13:00', '192.168.10.3', 443, 90 UNION ALL
SELECT '01/01/2019 13:00', '192.168.10.2', 80, 100 UNION ALL
SELECT '01/01/2019 13:00', '192.168.10.1', 443, 500
)
SELECT time, ip_address,
ARRAY_AGG(STRUCT(port, mbps) ORDER BY mbps DESC LIMIT 1)[OFFSET(0)].*
FROM `project.dataset.table`
GROUP BY time, ip_address
-- ORDER BY time, ip_address
结果
Row time ip_address port mbps
1 01/01/2019 12:20 192.168.10.1 80 120
2 01/01/2019 12:20 192.168.10.2 80 200
3 01/01/2019 12:40 192.168.10.1 443 300
4 01/01/2019 12:40 192.168.10.2 443 200
5 01/01/2019 12:40 192.168.10.3 443 300
6 01/01/2019 13:00 192.168.10.1 443 500
7 01/01/2019 13:00 192.168.10.2 80 100
8 01/01/2019 13:00 192.168.10.3 443 90
对于每 20 分钟的时间间隔,我试图找到带宽的最大值(下面 table 中的 mbps
列),每个唯一的 IP 地址生成,与相应的端口号。
每个 IP 地址在每 20 分钟内可能会或不会出现超过一次。每次在 20 分钟的时间间隔内记录一个 IP 地址时,列出的端口号可能相同也可能不同。
例如下面table中,ip地址192.168.10.1在12:20中出现了3次,端口号分别为443、80、80。在另一种情况下,IP 地址 192.168.10.2 在 12:40 期间出现两次,相同的端口号 443,列出两次,但 mbps(带宽)列的值不同。
目标是 select 并且只列出每个唯一的 IP 地址一次,对于每个二十分钟的时间段,按 mbps 降序排列。
table根据数据注入的时间进行分区。
我打算编写一个 cron 作业来自动执行此查询。 cron 作业将 运行 每小时,每周 7 天。查询将采用标准 SQL.
原table:
Row time ip_address port mbps
1 01/01/2019 12:20 192.168.10.1 443 100
2 01/01/2019 12:20 192.168.10.1 80 120
3 01/01/2019 12:20 192.168.10.2 80 200
4 01/01/2019 12:20 192.168.10.1 80 110
5 01/01/2019 12:40 192.168.10.2 443 200
6 01/01/2019 12:40 192.168.10.3 443 300
7 01/01/2019 12:40 192.168.10.2 443 200
8 01/01/2019 12:40 192.168.10.1 443 300
9 01/01/2019 13:00 192.168.10.3 443 90
10 01/01/2019 13:00 192.168.10.2 80 100
11 01/01/2019 13:00 192.168.10.1 443 500
执行下面的代码,
#standardSQL
SELECT
FORMAT_TIMESTAMP("%d/%m/%Y %H:%M", TIMESTAMP_SECONDS, 'Europe/London') AS time,
ip_address,
port,
SUM(bandwidth) AS mbps,
FROM
dataset1.table1
WHERE
_PARTITIONDATE = DATE_SUB(CURRENT_DATE(),INTERVAL 0 DAY)
AND timestamp > TIMESTAMP_ADD(CURRENT_TIMESTAMP(),INTERVAL -40 MINUTE)
GROUP BY
time,
ip_address,
port
ORDER BY
time,
mbps DESC
我明白了 table,
Row time ip_address port mbps
1 01/01/2019 12:20 192.168.10.2 80 200
2 01/01/2019 12:20 192.168.10.1 80 120
3 01/01/2019 12:20 192.168.10.1 80 110
4 01/01/2019 12:20 192.168.10.1 443 100
5 01/01/2019 12:40 192.168.10.1 443 300
6 01/01/2019 12:40 192.168.10.3 443 300
7 01/01/2019 12:40 192.168.10.2 25 200
8 01/01/2019 12:40 192.168.10.2 443 160
9 01/01/2019 13:00 192.168.10.1 443 500
10 01/01/2019 13:00 192.168.10.2 80 100
11 01/01/2019 13:00 192.168.10.3 443 90
这不是我想要的。相反,我想要这个:
Row time ip_address port mbps
1 01/01/2019 12:20 192.168.10.2 80 200
2 01/01/2019 12:20 192.168.10.1 80 120
3 01/01/2019 12:40 192.168.10.1 443 300
4 01/01/2019 12:40 192.168.10.3 443 300
5 01/01/2019 12:40 192.168.10.2 25 200
6 01/01/2019 13:00 192.168.10.1 443 500
7 01/01/2019 13:00 192.168.10.2 80 100
8 01/01/2019 13:00 192.168.10.3 443 90
我做错了什么?
以下适用于 BigQuery 标准 SQL
#standardSQL
SELECT time, ip_address,
ARRAY_AGG(STRUCT(port, mbps) ORDER BY mbps DESC LIMIT 1)[OFFSET(0)].*
FROM `project.dataset.table`
GROUP BY time, ip_address
您可以使用您问题中的示例数据来测试和使用上面的示例,如下例所示
#standardSQL
WITH `project.dataset.table` AS (
SELECT '01/01/2019 12:20' time, '192.168.10.1' ip_address, 443 port, 100 mbps UNION ALL
SELECT '01/01/2019 12:20', '192.168.10.1', 80, 120 UNION ALL
SELECT '01/01/2019 12:20', '192.168.10.2', 80, 200 UNION ALL
SELECT '01/01/2019 12:20', '192.168.10.1', 80, 110 UNION ALL
SELECT '01/01/2019 12:40', '192.168.10.2', 443, 200 UNION ALL
SELECT '01/01/2019 12:40', '192.168.10.3', 443, 300 UNION ALL
SELECT '01/01/2019 12:40', '192.168.10.2', 443, 200 UNION ALL
SELECT '01/01/2019 12:40', '192.168.10.1', 443, 300 UNION ALL
SELECT '01/01/2019 13:00', '192.168.10.3', 443, 90 UNION ALL
SELECT '01/01/2019 13:00', '192.168.10.2', 80, 100 UNION ALL
SELECT '01/01/2019 13:00', '192.168.10.1', 443, 500
)
SELECT time, ip_address,
ARRAY_AGG(STRUCT(port, mbps) ORDER BY mbps DESC LIMIT 1)[OFFSET(0)].*
FROM `project.dataset.table`
GROUP BY time, ip_address
-- ORDER BY time, ip_address
结果
Row time ip_address port mbps
1 01/01/2019 12:20 192.168.10.1 80 120
2 01/01/2019 12:20 192.168.10.2 80 200
3 01/01/2019 12:40 192.168.10.1 443 300
4 01/01/2019 12:40 192.168.10.2 443 200
5 01/01/2019 12:40 192.168.10.3 443 300
6 01/01/2019 13:00 192.168.10.1 443 500
7 01/01/2019 13:00 192.168.10.2 80 100
8 01/01/2019 13:00 192.168.10.3 443 90