在 bigquery 中编写最小值的优雅而有效的方法
Posted
技术标签:
【中文标题】在 bigquery 中编写最小值的优雅而有效的方法【英文标题】:Elegant and efficient way to write minimum in bigquery 【发布时间】:2019-09-28 11:58:11 【问题描述】:我有一个如下所示的表结构
我要做的是找到每组项目的最小值。我必须不断为不同的 itemid 组寻找最小值。虽然我的代码有效,但我确信这不是优雅而有效的方法。
找到最小值 WHERE itemid IN (1,2)
select subject_id,icu_id,value as min_val_1 FROM
(SELECT c.subject_id,c.time_1,d.min_time,d.max_time,c.value,c.icu_id,
row_number() OVER (PARTITION BY c.subject_id ORDER BY c.value,c.time_1) AS rank
from table_1 d
left join table_2 c
on c.subject_id = d.subject_id and (c.icu_id = d.icu_id_1 or c.icu_id = d.icu_id_2)
where c. itemid in
(1,2)) SBP
where rank = 1
order by subject_id,charttime
在 (3,4) 中找到 itemid 的最小值
select subject_id,icu_id,value as min_val_2 FROM
(SELECT c.subject_id,c.time_1,d.min_time,d.max_time,c.value,c.icu_id,
row_number() OVER (PARTITION BY c.subject_id ORDER BY c.value,c.time_1) AS rank
from table_1 d
left join table_2 c
on c.subject_id = d.subject_id and (c.icu_id = d.icu_id_1 or c.icu_id = d.icu_id_2)
where c. itemid in
(3,4)) SBP
where rank = 1
order by subject_id
如您所见,一切都一样。唯一的区别是itemid。有什么优雅的方式可以加入/合并这两者吗?你能帮帮我吗?
我希望我的输出是这样的?
【问题讨论】:
这是什么意思:“我要做的是找到每组项目的最小值。” 什么的最小值?什么组项?请澄清。 基于每个主题的项目 ID 的最小值 两个答案都很好并且被赞成。我选择将 Mikhail 答案标记为解决方案,因为它更有帮助且符合我的逻辑。感谢他们的意见。 。 .在这种情况下(我认为这是不常见的),我认为我的解决方案比 Mikhail 的解决方案更简单。他的回答通常很准确。 【参考方案1】:以下是 BigQuery 标准 SQL 并保留您的原始查询完全不变,同时仅添加缺少的和平(添加 cmets,以便您可以看到这些更改/添加)
#standardSQL
SELECT
subject_id,
icu_id,
MAX(IF(grp = 1, value, NULL)) AS min_val_1, -- changed
MAX(IF(grp = 2, value, NULL)) AS min_val_2 -- changed
FROM (
SELECT
c.subject_id,
c.time_1,
d.min_time,
d.max_time,
c.value,c.icu_id,
-- in below row - added element to PARTITION BY
ROW_NUMBER() OVER (PARTITION BY c.subject_id, CASE WHEN c.itemid IN (1, 2) THEN 1 WHEN c.itemid IN (3, 4) THEN 2 END ORDER BY c.value, c.time_1) AS RANK,
CASE WHEN c.itemid IN (1, 2) THEN 1 WHEN c.itemid IN (3, 4) THEN 2 END grp -- added
FROM table_1 d
LEFT JOIN table_2 c
ON c.subject_id = d.subject_id AND (c.icu_id = d.icu_id_1 OR c.icu_id = d.icu_id_2)
WHERE c.itemid IN (1, 2, 3, 4) -- changed
) SBP
WHERE RANK = 1
GROUP BY subject_id, icu_id -- added
ORDER BY subject_id
如果适用于您问题的样本数据 - 结果是
Row subject_id icu_id min_val_1 min_val_2
1 124 A1 10 19
2 199 B2 21 21
【讨论】:
您好,感谢您的回答。赞成。但是,我有一个问题。由于我是新来的查询,试图理解。如果 Gordon 的以下答案也将给出相同的输出,那么只写两行而不是这么长的查询是不是很容易。我错过的两个答案之间有什么区别吗? 我不想批评其他答案-但简而言之-它并没有真正完全反映您提出的问题和示例,因为它甚至根本不涉及 table_1 虽然它很重要初始查询中呈现的部分逻辑。所以我尽量保持您的查询不受影响,以保持 100% 的逻辑,而是回答具体问题 -Is there any elegant way to join/merge these two?
嗨,只是想一步一步地打破你的答案并理解它。所以在顶部的选择子句中,我们使用Max
还是Min
并不重要。由于每个主题只有一个记录,因此我们只选择其中一个,而不是另一个 row_number
操作。我的理解对吗?
另外,我想知道Bigquery中是否有类似NULLS LAST
的东西?我不希望对 NULLS 进行排名。
我确实在网上搜索并发现了ignore nulls
,但不知道该怎么做。【参考方案2】:
我认为您只需要条件聚合:
select t2.subject_id, t2.icu_id,
min(case when t2.item_id in (1, 2) then t2.value end) as value_1,
min(case when t2.item_id in (3, 4) then t2.value end) as value_2
from table_2 t2
group by t2.subject_id, t2.icu_id;
【讨论】:
赞成..谢谢...正在旅行..将很快更新答案..以上是关于在 bigquery 中编写最小值的优雅而有效的方法的主要内容,如果未能解决你的问题,请参考以下文章