如何在一个 SQL 查询中对不同的值进行分组并计算字段
How to group distinct values and calculate fields in one SQL query
这只是我第二次使用 Stack Overflow,所以我愿意接受任何关于如何更好地格式化我的问题的建设性批评。
我有一个订单列表,我想创建一个 table 有用的客户信息。
我创建了一个新的 table 来识别唯一客户(仅使用 select 不同的客户 ID),但我不确定是否有适当的功能来准确地对他们进行分组并生成基于其伴随字段的布尔值。
我需要新字段来显示一个布尔值,以确定客户的任何订单是否针对特定产品 SKU。
假设这是来源table
NAME | PRODUCT
------------
Andy | 1
Bill | 2
Cole | 2
Andy | 2
Bill | 1
Cole | 2
Dave | 3
我希望每个名称的输出只有唯一值,并附有一个布尔值,显示该给定名称的任何记录是否已收到该产品。
NAME | HAS1 | HAS2 | HAS3
--------------------------
Andy | true | true | false
Bill | true | true | false
Cole | false | true | false
Dave | false | false | true
您可以使用聚合和简单逻辑:
select name,
countif(product = 1) > 0 as has_1,
countif(product = 2) > 0 as has_2,
countif(product = 3) > 0 as has_3
from t
group by name;
您也可以使用 logical_or()
:
select name,
logic_or(product = 1) as has_1,
logic_or(product = 2) as has_2,
logic_or(product = 3) as has_3
from t
group by name;
以下适用于 BigQuery 标准 SQL
如果您事先知道产品名称(如您的示例中的“1”、“2”、“3”)并且数量很少 - 您可以使用以下简单版本
#standardSQL
SELECT name,
MAX(product = '1') AS has1,
MAX(product = '2') AS has2,
MAX(product = '3') AS has3
FROM `project.dataset.table`
GROUP BY name
如果应用于您问题中的示例数据(我假设您的产品是字符串数据类型)
WITH `project.dataset.table` AS (
SELECT 'Andy' name, '1' product UNION ALL
SELECT 'Bill', '2' UNION ALL
SELECT 'Cole', '2' UNION ALL
SELECT 'Andy', '2' UNION ALL
SELECT 'Bill', '1' UNION ALL
SELECT 'Cole', '2' UNION ALL
SELECT 'Dave', '3'
)
结果是
Row name has1 has2 has3
1 Andy true true false
2 Bill true true false
3 Cole false true false
4 Dave false false true
以防事先不知道产品名称and/or 产品数量多于少数 - 以下版本可以派上用场
EXECUTE IMMEDIATE '''
SELECT name,''' || (
SELECT STRING_AGG(DISTINCT "MAX(product = '" || product || "') AS has" || product)
FROM `project.dataset.table`
) || '''
FROM `project.dataset.table`
GROUP BY name
'''
具有完全相同的输出
正如您在此处看到的那样 - 整个查询是动态组合的,因此您无需担心产品数量及其名称
以下版本与上面相同,但更容易manage/read
EXECUTE IMMEDIATE FORMAT('''
SELECT name, %s
FROM `project.dataset.table`
GROUP BY name
''', (
SELECT STRING_AGG(DISTINCT "MAX(product = '" || product || "') AS has" || product)
FROM `project.dataset.table`
))
这只是我第二次使用 Stack Overflow,所以我愿意接受任何关于如何更好地格式化我的问题的建设性批评。
我有一个订单列表,我想创建一个 table 有用的客户信息。
我创建了一个新的 table 来识别唯一客户(仅使用 select 不同的客户 ID),但我不确定是否有适当的功能来准确地对他们进行分组并生成基于其伴随字段的布尔值。
我需要新字段来显示一个布尔值,以确定客户的任何订单是否针对特定产品 SKU。
假设这是来源table
NAME | PRODUCT
------------
Andy | 1
Bill | 2
Cole | 2
Andy | 2
Bill | 1
Cole | 2
Dave | 3
我希望每个名称的输出只有唯一值,并附有一个布尔值,显示该给定名称的任何记录是否已收到该产品。
NAME | HAS1 | HAS2 | HAS3
--------------------------
Andy | true | true | false
Bill | true | true | false
Cole | false | true | false
Dave | false | false | true
您可以使用聚合和简单逻辑:
select name,
countif(product = 1) > 0 as has_1,
countif(product = 2) > 0 as has_2,
countif(product = 3) > 0 as has_3
from t
group by name;
您也可以使用 logical_or()
:
select name,
logic_or(product = 1) as has_1,
logic_or(product = 2) as has_2,
logic_or(product = 3) as has_3
from t
group by name;
以下适用于 BigQuery 标准 SQL
如果您事先知道产品名称(如您的示例中的“1”、“2”、“3”)并且数量很少 - 您可以使用以下简单版本
#standardSQL
SELECT name,
MAX(product = '1') AS has1,
MAX(product = '2') AS has2,
MAX(product = '3') AS has3
FROM `project.dataset.table`
GROUP BY name
如果应用于您问题中的示例数据(我假设您的产品是字符串数据类型)
WITH `project.dataset.table` AS (
SELECT 'Andy' name, '1' product UNION ALL
SELECT 'Bill', '2' UNION ALL
SELECT 'Cole', '2' UNION ALL
SELECT 'Andy', '2' UNION ALL
SELECT 'Bill', '1' UNION ALL
SELECT 'Cole', '2' UNION ALL
SELECT 'Dave', '3'
)
结果是
Row name has1 has2 has3
1 Andy true true false
2 Bill true true false
3 Cole false true false
4 Dave false false true
以防事先不知道产品名称and/or 产品数量多于少数 - 以下版本可以派上用场
EXECUTE IMMEDIATE '''
SELECT name,''' || (
SELECT STRING_AGG(DISTINCT "MAX(product = '" || product || "') AS has" || product)
FROM `project.dataset.table`
) || '''
FROM `project.dataset.table`
GROUP BY name
'''
具有完全相同的输出
正如您在此处看到的那样 - 整个查询是动态组合的,因此您无需担心产品数量及其名称
以下版本与上面相同,但更容易manage/read
EXECUTE IMMEDIATE FORMAT('''
SELECT name, %s
FROM `project.dataset.table`
GROUP BY name
''', (
SELECT STRING_AGG(DISTINCT "MAX(product = '" || product || "') AS has" || product)
FROM `project.dataset.table`
))