在 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 中编写最小值的优雅而有效的方法的主要内容,如果未能解决你的问题,请参考以下文章

验证字段值的有效方法 Spark

在抛出非正值的同时获得两个价格之间的最小值的优雅方式

寻找For循环数组C ++中最大和最小值的值

报告 data.frame 中缺失值的优雅方式

BigQuery 中的优雅时区转换

Python:优雅而有效的屏蔽列表的方法