我有一个巨大的 BigQuery 表“taskperformance”,它将任务归因于销售(在本例中进行排序是为了更容易 理解):
销售_id | 销售_时间戳 | 任务id | 任务_时间戳 | 是同一个商店 | is_retail_task |
---|---|---|---|---|---|
S123 | 2024-01-06 10:00:00 世界标准时间 | T1 | 2024-01-05 09:00:00 世界标准时间 | 正确 | 正确 |
S123 | 2024-01-06 10:00:00 世界标准时间 | T2 | 2024-01-04 10:00:00 世界标准时间 | 错误 | 错误 |
S123 | 2024-01-06 10:00:00 世界标准时间 | T3 | 2024-01-03 14:00:00 世界标准时间 | 正确 | 错误 |
S123 | 2024-01-06 10:00:00 世界标准时间 | T4 | 2024-01-02 16:00:00 世界标准时间 | 正确 | 正确 |
S456 | 2024-02-15 09:30:00 世界标准时间 | T5 | 2024-02-14 15:00:00 世界标准时间 | 正确 | 错误 |
S456 | 2024-02-15 09:30:00 世界标准时间 | T6 | 2024-02-13 12:00:00 世界标准时间 | 错误 | 正确 |
S456 | 2024-02-15 09:30:00 世界标准时间 | T7 | 2024-02-12 11:00:00 世界标准时间 | 正确 | 正确 |
我想在此表中添加两列:
所以我想获得这个:
销售_id | 销售_时间戳 | 任务id | 任务_时间戳 | 是同一个商店 | is_retail_task | 相同商店排名 | 零售_任务_排名 |
---|---|---|---|---|---|---|---|
S123 | 2024-01-06 10:00:00 世界标准时间 | T1 | 2024-01-05 09:00:00 世界标准时间 | 真实 | 真实 | 1 | 1 |
S123 | 2024-01-06 10:00:00 世界标准时间 | T2 | 2024-01-04 10:00:00 世界标准时间 | 假 | 假 | 空 | 空 |
S123 | 2024-01-06 10:00:00 世界标准时间 | T3 | 2024-01-03 14:00:00 世界标准时间 | 真实 | 假 | 2 | 空 |
S123 | 2024-01-06 10:00:00 世界标准时间 | T4 | 2024-01-02 16:00:00 世界标准时间 | 真实 | 真实 | 3 | 2 |
S456 | 2024-02-15 09:30:00 世界标准时间 | T5 | 2024-02-14 15:00:00 世界标准时间 | 真实 | 假 | 1 | 空 |
S456 | 2024-02-15 09:30:00 世界标准时间 | T6 | 2024-02-13 12:00:00 世界标准时间 | 假 | 真实 | 空 | 1 |
S456 | 2024-02-15 09:30:00 世界标准时间 | T7 | 2024-02-12 11:00:00 世界标准时间 | 真实 | 真实 | 2 | 2 |
但在应用 RANK() 之前,我似乎找不到一种方法来过滤窗口函数内的条件。
当我尝试时,条件为假的行的排名仍然会增加:
WITH taskperformance AS (
SELECT 'S123' AS sale_id, TIMESTAMP('2024-01-06 10:00:00 UTC') AS sale_timestamp, 'T1' AS task_id, TIMESTAMP('2024-01-05 09:00:00 UTC') AS task_timestamp, TRUE AS is_same_store, TRUE AS is_retail_task
UNION ALL
SELECT 'S123', TIMESTAMP('2024-01-06 10:00:00 UTC'), 'T2', TIMESTAMP('2024-01-04 10:00:00 UTC'), FALSE, FALSE
UNION ALL
SELECT 'S123', TIMESTAMP('2024-01-06 10:00:00 UTC'), 'T3', TIMESTAMP('2024-01-03 14:00:00 UTC'), TRUE, FALSE
UNION ALL
SELECT 'S123', TIMESTAMP('2024-01-06 10:00:00 UTC'), 'T4', TIMESTAMP('2024-01-02 16:00:00 UTC'), TRUE, TRUE
UNION ALL
SELECT 'S456', TIMESTAMP('2024-02-15 09:30:00 UTC'), 'T5', TIMESTAMP('2024-02-14 15:00:00 UTC'), TRUE, FALSE
UNION ALL
SELECT 'S456', TIMESTAMP('2024-02-15 09:30:00 UTC'), 'T6', TIMESTAMP('2024-02-13 12:00:00 UTC'), FALSE, TRUE
UNION ALL
SELECT 'S456', TIMESTAMP('2024-02-15 09:30:00 UTC'), 'T7', TIMESTAMP('2024-02-12 11:00:00 UTC'), TRUE, TRUE
)
SELECT
*,
CASE WHEN is_same_store THEN
RANK() OVER (PARTITION BY sale_id ORDER BY task_timestamp DESC)
END AS same_store_rank,
CASE WHEN is_retail_task THEN
RANK() OVER (PARTITION BY sale_id ORDER BY task_timestamp DESC)
END AS retail_task_rank
FROM taskperformance
ORDER BY task_id
销售_id | 销售_时间戳 | 任务ID | 任务_时间戳 | 是同一个商店 | is_retail_task | 相同商店排名 | 零售_任务_排名 |
---|---|---|---|---|---|---|---|
S123 | 2024-01-06 10:00:00 世界标准时间 | T1 | 2024-01-05 09:00:00 世界标准时间 | 真实 | 真实 | 1 | 1 |
S123 | 2024-01-06 10:00:00 世界标准时间 | T2 | 2024-01-04 10:00:00 世界标准时间 | 假 | 假 | 空 | 空 |
S123 | 2024-01-06 10:00:00 世界标准时间 | T3 | 2024-01-03 14:00:00 世界标准时间 | 真实 | 假 | 3 | 空 |
S123 | 2024-01-06 10:00:00 世界标准时间 | T4 | 2024-01-02 16:00:00 世界标准时间 | 真实 | 真实 | 4 | 4 |
S456 | 2024-02-15 09:30:00 世界标准时间 | T5 | 2024-02-14 15:00:00 世界标准时间 | 真实 | 假 | 1 | 空 |
S456 | 2024-02-15 09:30:00 世界标准时间 | T6 | 2024-02-13 12:00:00 世界标准时间 | 假 | 真实 | 空 | 2 |
S456 | 2024-02-15 09:30:00 世界标准时间 | T7 | 2024-02-12 11:00:00 世界标准时间 | 真实 | 真实 | 3 | 3 |
例如,对于 same_store_rank,我得到 [1, NULL, 3, 4] 而不是 [1, NULL, 2, 3]
我认为这可以使用 CTE 和 WHERE 子句来完成,然后加入任务性能表,但这似乎 浪费了读这个表 3 遍的时间:
WITH
taskperformance AS (
SELECT 'S123' AS sale_id, TIMESTAMP('2024-01-06 10:00:00 UTC') AS sale_timestamp, 'T1' AS task_id, TIMESTAMP('2024-01-05 09:00:00 UTC') AS task_timestamp, TRUE AS is_same_store, TRUE AS is_retail_task
UNION ALL
SELECT 'S123', TIMESTAMP('2024-01-06 10:00:00 UTC'), 'T2', TIMESTAMP('2024-01-04 10:00:00 UTC'), FALSE, FALSE
UNION ALL
SELECT 'S123', TIMESTAMP('2024-01-06 10:00:00 UTC'), 'T3', TIMESTAMP('2024-01-03 14:00:00 UTC'), TRUE, FALSE
UNION ALL
SELECT 'S123', TIMESTAMP('2024-01-06 10:00:00 UTC'), 'T4', TIMESTAMP('2024-01-02 16:00:00 UTC'), TRUE, TRUE
UNION ALL
SELECT 'S456', TIMESTAMP('2024-02-15 09:30:00 UTC'), 'T5', TIMESTAMP('2024-02-14 15:00:00 UTC'), TRUE, FALSE
UNION ALL
SELECT 'S456', TIMESTAMP('2024-02-15 09:30:00 UTC'), 'T6', TIMESTAMP('2024-02-13 12:00:00 UTC'), FALSE, TRUE
UNION ALL
SELECT 'S456', TIMESTAMP('2024-02-15 09:30:00 UTC'), 'T7', TIMESTAMP('2024-02-12 11:00:00 UTC'), TRUE, TRUE
),
same_store_ranks AS (
SELECT sale_id, task_id, RANK() OVER (PARTITION BY sale_id ORDER BY task_timestamp DESC) AS same_store_rank
FROM taskperformance
WHERE is_same_store
),
retail_task_ranks AS (
SELECT sale_id, task_id, RANK() OVER (PARTITION BY sale_id ORDER BY task_timestamp DESC) AS retail_task_rank
FROM taskperformance
WHERE is_retail_task
)
SELECT *
FROM taskperformance
LEFT JOIN same_store_ranks
USING(sale_id, task_id)
LEFT JOIN retail_task_ranks
USING(sale_id, task_id)
ORDER BY task_id
这样做,我得到了预期的结果,但我想避免多次读取任务性能,然后不得不 JOIN,因为代码很冗长,而且我认为多次读取巨大的任务性能表对 表现。特别是因为我还有其他排名列要添加,而不仅仅是本例中的两个。
您可以按相关列进行分区以获得连续排名
SELECT
*,
CASE WHEN is_same_store THEN
RANK() OVER (PARTITION BY sale_id, is_same_store ORDER BY task_timestamp DESC)
END AS same_store_rank,
CASE WHEN is_retail_task THEN
RANK() OVER (PARTITION BY sale_id, is_retail_task ORDER BY task_timestamp DESC)
END AS retail_task_rank
FROM taskperformance
ORDER BY task_id