如何在 ANSI SQL 中完成 "cascading grouping" 列?
How do I accomplish "cascading grouping" of columns in ANSI SQL?
我有一个 Presto SQL table 看起来像这样:
|tenant|type|environment |
| |
| X | A |http:a.b.c(foo)/http:a.b.c(bar)/http:a.b.c(baz)|
| X | A |http:d.e.f(foo)/http:d.e.f(bar)/http:d.e.f(baz)|
| X | A |http:g.h.i(foo) |
| X | B |http:g.h.i(foo)/http:g.h.i(bar) |
所有列的类型都是字符串。
我需要生成计算每个租户和类型的每种环境类型(foo、bar 或 baz)的输出。 IE。上面的数据应该像这样列出:
X A foo 3
bar 2
baz 2
X B foo 1
bar 1
我一直在尝试这样的查询:
SELECT "tenant_id", "type_id", "environment", count(*) AS total_count
FROM "tenant_table"
WHERE "environment" LIKE '%foo%'
GROUP BY "tenant_id", "type_id", "environment";
但是我没有得到我需要的输出。我在更改数据类型方面确实有一点灵活性。数据最初来自 CSV 文件。例如,如果将“环境”列的类型重新定义为数组之类的类型会使事情变得更容易,那么这是一个选项。解决此问题的任何帮助将不胜感激。谢谢。
如果这是一个固定的值列表,每个字符串最多出现 1 次,您可以将其放入派生 table 并使用 like
搜索匹配项:
select t.tenant, t.type, v.val, count(*) cnt
from tenant_db t
inner join (values ('foo'), ('bar'), ('baz')) v(val)
on t.environment like '%' || v.val || '%'
group by t.tenant, t.type, v.val
根据您的要求,您可能希望缩小搜索条件以避免误报;也许使用括号:
on t.environment like '%(' || v.val || ')%'
或者使用正则表达式。
您可以使用 regexp_extract_all
and use UNNEST
提取值以在计算聚合之前“展平”结果数组:
WITH data(tenant, type, environment) AS (
VALUES
('X', 'A', 'http:a.b.c(foo)/http:a.b.c(bar)/http:a.b.c(baz)'),
('X', 'A', 'http:d.e.f(foo)/http:d.e.f(bar)/http:d.e.f(baz)'),
('X', 'A', 'http:g.h.i(foo)'),
('X', 'B', 'http:g.h.i(foo)/http:g.h.i(bar)')
)
SELECT tenant, type, value, count(*)
FROM data, UNNEST(regexp_extract_all(data.environment, '\(([^\)]+)\)', 1)) t(value)
GROUP BY tenant, type, value
产生:
tenant | type | value | _col3
--------+------+-------+-------
X | A | baz | 2
X | A | bar | 2
X | A | foo | 3
X | B | bar | 1
X | B | foo | 1
我有一个 Presto SQL table 看起来像这样:
|tenant|type|environment |
| |
| X | A |http:a.b.c(foo)/http:a.b.c(bar)/http:a.b.c(baz)|
| X | A |http:d.e.f(foo)/http:d.e.f(bar)/http:d.e.f(baz)|
| X | A |http:g.h.i(foo) |
| X | B |http:g.h.i(foo)/http:g.h.i(bar) |
所有列的类型都是字符串。 我需要生成计算每个租户和类型的每种环境类型(foo、bar 或 baz)的输出。 IE。上面的数据应该像这样列出:
X A foo 3
bar 2
baz 2
X B foo 1
bar 1
我一直在尝试这样的查询:
SELECT "tenant_id", "type_id", "environment", count(*) AS total_count
FROM "tenant_table"
WHERE "environment" LIKE '%foo%'
GROUP BY "tenant_id", "type_id", "environment";
但是我没有得到我需要的输出。我在更改数据类型方面确实有一点灵活性。数据最初来自 CSV 文件。例如,如果将“环境”列的类型重新定义为数组之类的类型会使事情变得更容易,那么这是一个选项。解决此问题的任何帮助将不胜感激。谢谢。
如果这是一个固定的值列表,每个字符串最多出现 1 次,您可以将其放入派生 table 并使用 like
搜索匹配项:
select t.tenant, t.type, v.val, count(*) cnt
from tenant_db t
inner join (values ('foo'), ('bar'), ('baz')) v(val)
on t.environment like '%' || v.val || '%'
group by t.tenant, t.type, v.val
根据您的要求,您可能希望缩小搜索条件以避免误报;也许使用括号:
on t.environment like '%(' || v.val || ')%'
或者使用正则表达式。
您可以使用 regexp_extract_all
and use UNNEST
提取值以在计算聚合之前“展平”结果数组:
WITH data(tenant, type, environment) AS (
VALUES
('X', 'A', 'http:a.b.c(foo)/http:a.b.c(bar)/http:a.b.c(baz)'),
('X', 'A', 'http:d.e.f(foo)/http:d.e.f(bar)/http:d.e.f(baz)'),
('X', 'A', 'http:g.h.i(foo)'),
('X', 'B', 'http:g.h.i(foo)/http:g.h.i(bar)')
)
SELECT tenant, type, value, count(*)
FROM data, UNNEST(regexp_extract_all(data.environment, '\(([^\)]+)\)', 1)) t(value)
GROUP BY tenant, type, value
产生:
tenant | type | value | _col3
--------+------+-------+-------
X | A | baz | 2
X | A | bar | 2
X | A | foo | 3
X | B | bar | 1
X | B | foo | 1