如何在大查询中应用:count(distinct ...) over (partition by ... order by)?
How to apply: count(distinct ...) over (partition by ... order by) in big query?
我目前有这个 source table。
我正在尝试从 GCP BigQuery 上 SQL 中的第一个 table 中获取 this second table。
我的查询如下:
SELECT
SE.MARKET_ID,
SE.LOCAL_POS_ID,
SE.BC_ID,
LEFT(SE.SALE_CREATION_DATE,6) AS DATE_ID_MONTH,
COUNT(DISTINCT
CASE
WHEN FLAG
THEN SE.CUST_ID
END)
OVER (PARTITION BY SE.MARKET_ID, SE.LOCAL_POS_ID, SE.BC_ID, LEFT(SE.SALE_CREATION_DATE,4) ORDER BY LEFT(SE.SALE_CREATION_DATE,6)) AS NB_ACTIVE_CUSTOMERS
FROM
SE
GROUP BY
SE.MARKET_ID, SE.LOCAL_POS_ID, SE.BC_ID, LEFT(SE.SALE_CREATION_DATE,6)
但是,我得到这个错误,我没有成功绕过:
Window ORDER BY is not allowed if DISTINCT is specified at [12:107]
我无法使用以下请求创建以前的 table :
SELECT DISTINCT
SE.MARKET_ID,
SE.LOCAL_POS_ID,
SE.BC_ID,
LEFT(SE.SALE_CREATION_DATE,6) AS DATE_ID_MONTH,
CASE
WHEN FLAG
THEN SE.CUST_ID
ELSE NULL
END AS VALID_CUST_ID
FROM
SE
为了在那之后使用 dense_rank() 因为我还有 50 个其他指标(和 500M 行)要添加到这个 table(基于其他标志的指标)并且我可以'显然没有为它们中的每一个创建一个 WITH,我只需要几个 WITH 或 none(就像我当前的查询应该做的那样)。
有人知道我该如何处理吗?
我认为您的某些示例数据不正确,但我确实使用过它并得到了匹配的结果,至少对于 MPE 数据是这样。您可以通过首先在 CUST_ID
上用额外分区标记“不同计数”的行,然后首先在 FLAG DESC
上排序来完成此操作。然后你会以你希望应用 count(distinct <expr>) over ...
的相同方式总结它
WITH SE AS (
SELECT 1 LINE_ID, 'TW' MARKET_ID, 'X' LOCAL_POS_ID, 'MPE' BC_ID,
1 CUST_ID, '20200201' SALE_CREATION_DATE, 1 FLAG UNION ALL
SELECT 2, 'TW', 'X', 'MPE', 2, '20201005', 1 UNION ALL
SELECT 3, 'TW', 'X', 'MPE', 3, '20200415', 0 UNION ALL
SELECT 4, 'TW', 'X', 'MPE', 1, '20200223', 1 UNION ALL
SELECT 5, 'TW', 'X', 'MPE', 6, '20200217', 1 UNION ALL
SELECT 6, 'TW', 'X', 'MPE', 9, '20200715', 1 UNION ALL
SELECT 7, 'TW', 'X', 'MPE', 4, '20200223', 1 UNION ALL
SELECT 8, 'TW', 'X', 'MPE', 1, '20201008', 1 UNION ALL
SELECT 9, 'TW', 'X', 'MPE', 2, '20201019', 1 UNION ALL
SELECT 10, 'TW', 'X', 'MPE', 1, '20200516', 1 UNION ALL
SELECT 11, 'TW', 'X', 'MPE', 1, '20200129', 1 UNION ALL
SELECT 12, 'TW', 'X', 'MPE', 1, '20201007', 1 UNION ALL
SELECT 13, 'TW', 'X', 'MPE', 2, '20201005', 1 UNION ALL
SELECT 14, 'TW', 'X', 'MPE', 3, '20200505', 1 UNION ALL
SELECT 15, 'TW', 'X', 'MPE', 8, '20201103', 1 UNION ALL
SELECT 16, 'TW', 'X', 'MPE', 9, '20200820', 1
),
DATA AS (
SELECT *,
LEFT(SALE_CREATION_DATE, 6) AS SALE_MONTH,
LEFT(SALE_CREATION_DATE, 4) AS SALE_YEAR,
CASE ROW_NUMBER() OVER (
PARTITION BY MARKET_ID, LOCAL_POS_ID, BC_ID,
LEFT(SALE_CREATION_DATE, 4), CUST_ID
ORDER BY FLAG DESC, LEFT(SALE_CREATION_DATE, 6)
) WHEN 1 THEN FLAG END AS COUNTER /* assumes possible to have no flagged row */
FROM SE
)
SELECT MARKET_ID, LOCAL_POS_ID, BC_ID, SALE_MONTH,
SUM(SUM(COUNTER)) OVER (
PARTITION BY MARKET_ID, LOCAL_POS_ID, BC_ID, SALE_YEAR
ORDER BY SALE_MONTH
) AS NB_ACTIVE_CUSTOMERS
FROM DATA
GROUP BY MARKET_ID, LOCAL_POS_ID, BC_ID, SALE_YEAR, SALE_MONTH
ORDER BY MARKET_ID, LOCAL_POS_ID, BC_ID, SALE_YEAR, SALE_MONTH
考虑以下方法
select * except(ids),
array_length(array(
select distinct id
from unnest(split(ids)) id
)) as nb_active_customers,
format('%t', array(
select distinct id
from unnest(split(ids)) id
)) as distinct_values
from (
select market_id, local_pos_id, bc_id, date_id_month,
string_agg('' || ids) over(partition by market_id order by date_id_month) ids
from (
select market_id, local_pos_id, bc_id, left(sale_creation_date,6) AS date_id_month,
string_agg('' || cust_id) ids
from se
where flag = 1
group by market_id, local_pos_id, bc_id, date_id_month
)
) t
如果应用于您问题中的示例数据 - 输出为
我目前有这个 source table。
我正在尝试从 GCP BigQuery 上 SQL 中的第一个 table 中获取 this second table。
我的查询如下:
SELECT
SE.MARKET_ID,
SE.LOCAL_POS_ID,
SE.BC_ID,
LEFT(SE.SALE_CREATION_DATE,6) AS DATE_ID_MONTH,
COUNT(DISTINCT
CASE
WHEN FLAG
THEN SE.CUST_ID
END)
OVER (PARTITION BY SE.MARKET_ID, SE.LOCAL_POS_ID, SE.BC_ID, LEFT(SE.SALE_CREATION_DATE,4) ORDER BY LEFT(SE.SALE_CREATION_DATE,6)) AS NB_ACTIVE_CUSTOMERS
FROM
SE
GROUP BY
SE.MARKET_ID, SE.LOCAL_POS_ID, SE.BC_ID, LEFT(SE.SALE_CREATION_DATE,6)
但是,我得到这个错误,我没有成功绕过:
Window ORDER BY is not allowed if DISTINCT is specified at [12:107]
我无法使用以下请求创建以前的 table :
SELECT DISTINCT
SE.MARKET_ID,
SE.LOCAL_POS_ID,
SE.BC_ID,
LEFT(SE.SALE_CREATION_DATE,6) AS DATE_ID_MONTH,
CASE
WHEN FLAG
THEN SE.CUST_ID
ELSE NULL
END AS VALID_CUST_ID
FROM
SE
为了在那之后使用 dense_rank() 因为我还有 50 个其他指标(和 500M 行)要添加到这个 table(基于其他标志的指标)并且我可以'显然没有为它们中的每一个创建一个 WITH,我只需要几个 WITH 或 none(就像我当前的查询应该做的那样)。
有人知道我该如何处理吗?
我认为您的某些示例数据不正确,但我确实使用过它并得到了匹配的结果,至少对于 MPE 数据是这样。您可以通过首先在 CUST_ID
上用额外分区标记“不同计数”的行,然后首先在 FLAG DESC
上排序来完成此操作。然后你会以你希望应用 count(distinct <expr>) over ...
WITH SE AS (
SELECT 1 LINE_ID, 'TW' MARKET_ID, 'X' LOCAL_POS_ID, 'MPE' BC_ID,
1 CUST_ID, '20200201' SALE_CREATION_DATE, 1 FLAG UNION ALL
SELECT 2, 'TW', 'X', 'MPE', 2, '20201005', 1 UNION ALL
SELECT 3, 'TW', 'X', 'MPE', 3, '20200415', 0 UNION ALL
SELECT 4, 'TW', 'X', 'MPE', 1, '20200223', 1 UNION ALL
SELECT 5, 'TW', 'X', 'MPE', 6, '20200217', 1 UNION ALL
SELECT 6, 'TW', 'X', 'MPE', 9, '20200715', 1 UNION ALL
SELECT 7, 'TW', 'X', 'MPE', 4, '20200223', 1 UNION ALL
SELECT 8, 'TW', 'X', 'MPE', 1, '20201008', 1 UNION ALL
SELECT 9, 'TW', 'X', 'MPE', 2, '20201019', 1 UNION ALL
SELECT 10, 'TW', 'X', 'MPE', 1, '20200516', 1 UNION ALL
SELECT 11, 'TW', 'X', 'MPE', 1, '20200129', 1 UNION ALL
SELECT 12, 'TW', 'X', 'MPE', 1, '20201007', 1 UNION ALL
SELECT 13, 'TW', 'X', 'MPE', 2, '20201005', 1 UNION ALL
SELECT 14, 'TW', 'X', 'MPE', 3, '20200505', 1 UNION ALL
SELECT 15, 'TW', 'X', 'MPE', 8, '20201103', 1 UNION ALL
SELECT 16, 'TW', 'X', 'MPE', 9, '20200820', 1
),
DATA AS (
SELECT *,
LEFT(SALE_CREATION_DATE, 6) AS SALE_MONTH,
LEFT(SALE_CREATION_DATE, 4) AS SALE_YEAR,
CASE ROW_NUMBER() OVER (
PARTITION BY MARKET_ID, LOCAL_POS_ID, BC_ID,
LEFT(SALE_CREATION_DATE, 4), CUST_ID
ORDER BY FLAG DESC, LEFT(SALE_CREATION_DATE, 6)
) WHEN 1 THEN FLAG END AS COUNTER /* assumes possible to have no flagged row */
FROM SE
)
SELECT MARKET_ID, LOCAL_POS_ID, BC_ID, SALE_MONTH,
SUM(SUM(COUNTER)) OVER (
PARTITION BY MARKET_ID, LOCAL_POS_ID, BC_ID, SALE_YEAR
ORDER BY SALE_MONTH
) AS NB_ACTIVE_CUSTOMERS
FROM DATA
GROUP BY MARKET_ID, LOCAL_POS_ID, BC_ID, SALE_YEAR, SALE_MONTH
ORDER BY MARKET_ID, LOCAL_POS_ID, BC_ID, SALE_YEAR, SALE_MONTH
考虑以下方法
select * except(ids),
array_length(array(
select distinct id
from unnest(split(ids)) id
)) as nb_active_customers,
format('%t', array(
select distinct id
from unnest(split(ids)) id
)) as distinct_values
from (
select market_id, local_pos_id, bc_id, date_id_month,
string_agg('' || ids) over(partition by market_id order by date_id_month) ids
from (
select market_id, local_pos_id, bc_id, left(sale_creation_date,6) AS date_id_month,
string_agg('' || cust_id) ids
from se
where flag = 1
group by market_id, local_pos_id, bc_id, date_id_month
)
) t
如果应用于您问题中的示例数据 - 输出为