[英]How to UPIVOT all columns in a table and aggregate into Data Quality/ Validation Metrics? SQL SNOWFLAKE
我有一個包含 60 多列的表,我想 UNPIVOT 以便每一列變成一行,然后找到每個條目的填充率、最小值和最大值。
例如
ID | 開始日期 | 結束日期 | EVENT_ID | PROVIDER_CODE |
---|---|---|---|---|
01 | 21 年 1 月 23 日 | 21 年 3 月 14 日 | 0023401 | 0012323 |
02 | 21 年 6 月 4 日 | 21 年 9 月 20 日 | 0025906 | 0023454 |
03 | 21 年 7 月 20 日 | 12/02/21 | 0027093 | 0034983 |
我希望 output 看起來像
列名 | 填充率 | 敏 | 最大限度 |
---|---|---|---|
ID | 0.7934 | 01 | 03 |
開始日期 | 0.6990 | 21 年 1 月 23 日 | 21 年 7 月 20 日 |
結束日期 | 0.9089 | 21 年 3 月 14 日 | 12/02/21 |
事件 ID | 1.0000 | 0023401 | 0027093 |
努力得到想要的 output,尤其是因為不同列中的數據類型不同
我嘗試執行以下操作,但它不允許在 unpivot 中使用 agg 函數
select *
from "DSVC_MERCKPAN_PROD"."COHORTS_LATEST"."MEDICAL_HEADERS"
UNPIVOT (
max(code) as max_value,
min(code) as min_value,
avg(code) as fill_rate,
code as column_name
)
對於填充率,我嘗試使用此邏輯,因為始終填充 ID,因此它具有總行數,但是其他列可以是 null
(COUNT_IF(start_date is not null))/(COUNT_IF(ID is not null))) as FILL_RATE,
我有 2 個想法來實施該報告。
第一種方法是將所有值轉換為VARCHAR
然后使用UNPIVOT
:
-- Generate dummy data
create or replace table t1 (c1 int, c2 int, c3 int, c4 int, c5 int, c6 int, c7 int, c8 int, c9 int, c10 int) as
select
iff(random()%2=0, random(), null), iff(random()%2=0, random(), null),
iff(random()%2=0, random(), null), iff(random()%2=0, random(), null),
iff(random()%2=0, random(), null), iff(random()%2=0, random(), null),
iff(random()%2=0, random(), null), iff(random()%2=0, random(), null),
iff(random()%2=0, random(), null), iff(random()%2=0, random(), null)
from table(generator(rowcount => 1000000000))
;
-- Query
with
cols as (
select column_name, ordinal_position
from information_schema.columns
where table_catalog = current_database()
and table_schema = current_schema()
and table_name = 'T1'
),
stringified as (
select
c1::varchar c1, c2::varchar c2, c3::varchar c3, c4::varchar c4, c5::varchar c5,
c6::varchar c6, c7::varchar c7, c8::varchar c8, c9::varchar c9, c10::varchar c10
from t1
),
data as (
select column_name, column_value
from stringified
unpivot(column_value for column_name in (c1, c2, c3, c4, c5, c6, c7, c8, c9, c10))
)
select
c.column_name,
count(d.column_value)/(select count(*) from t1) fill_rate,
min(d.column_value) min,
max(d.column_value) max
from cols c
left join data d using (column_name)
group by c.column_name, c.ordinal_position
order by c.ordinal_position
;
/*
COLUMN_NAME FILL_RATE MIN MAX
C1 0.500000 -1000000069270747870 999999972962694409
C2 0.499980 -1000000027928146782 999999946877079818
C3 0.499996 -1000000012155323098 999999942281548701
C4 0.500017 -1000000056353213091 999999946421698482
C5 0.500015 -1000000015608859996 999999993977648967
C6 0.500003 -1000000007081089270 999999998851014730
C7 0.499987 -100000008605944993 999999968272328033
C8 0.499992 -1000000042470913027 999999977402822725
C9 0.500011 -1000000058928465662 999999969060696774
C10 0.500029 -1000000011306371004 99999996061390938
*/
這是一種簡單的方法,但它仍然需要列出所有列名兩次,並且在列數非常大的情況下有點困難(但我相信它比巨大的 UNION ALL 查詢要好得多)。
另一種解決方案有點棘手,但如果行長度不超過 VARIANT 值限制 (16 MiB),您可以使用OBJECT_CONSTRUCT(*)
聚合來取消透視表:
with
cols as (
select column_name, ordinal_position
from information_schema.columns
where table_catalog = current_database()
and table_schema = current_schema()
and table_name = 'T1'
),
data as (
select f.key column_name, f.value::varchar column_value
from (select object_construct(*) rec from t1) up,
lateral flatten(up.rec) f
)
select
c.column_name,
count(d.column_value)/(select count(*) from t1) fill_rate,
min(d.column_value) min,
max(d.column_value) max
from cols c
left join data d using (column_name)
group by c.column_name, c.ordinal_position
order by c.ordinal_position
;
/*
COLUMN_NAME FILL_RATE MIN MAX
C1 0.500000 -1000000069270747870 999999972962694409
C2 0.499980 -1000000027928146782 999999946877079818
C3 0.499996 -1000000012155323098 999999942281548701
C4 0.500017 -1000000056353213091 999999946421698482
C5 0.500015 -1000000015608859996 999999993977648967
C6 0.500003 -1000000007081089270 999999998851014730
C7 0.499987 -100000008605944993 999999968272328033
C8 0.499992 -1000000042470913027 999999977402822725
C9 0.500011 -1000000058928465662 999999969060696774
C10 0.500029 -1000000011306371004 99999996061390938
*/
OBJECT_CONSTRUCT(*)
聚合是OBJECT_CONSTRUCT
function 的一種特殊用法,它提取列名作為每個 JSON ZA8CFDE6331BD59EB26666ZC4 的鍵。 據我所知,這是以編程方式從表中提取列名以及值的唯一方法。
由於OBJECT_CONSTRUCT
是一個比較繁重的操作,它通常比第一種解決方案需要更長的時間,但是你不需要用這個技巧寫所有的列名。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.