如何在 SQL 语句中获取非分组列(类似于 MySQL)

Posted

技术标签:

【中文标题】如何在 SQL 语句中获取非分组列(类似于 MySQL)【英文标题】:How to get non grouped-by columns in SQL statement (similar to in MySQL) 【发布时间】:2019-02-19 17:56:58 【问题描述】:

mysql 中,我可以执行以下查询:

select first_name from `table` group by age

但是,如果我在 BigQuery 中执行类似操作,则会收到以下错误:

SELECT 列表表达式引用既不分组也不聚合的列 first_name

我们如何在 BigQuery 中编写等效的 mysql 聚合查询?

【问题讨论】:

实际上,最新版本的 MySQL 默认禁用了该功能,因为此类查询通常被认为是错误的。该查询为您提供了来自每个年龄的有效随机选择 (first_name, last_name)。 @Uueerdo——没关系。这就是我真正想要的。 您希望从此类查询中获得什么行为? @Pedro 请看上面的截图。 那张截图是你想要的,还是你得到的? 【参考方案1】:

以下是 BigQuery 标准 SQL,如下所示:

#standardSQL
SELECT ANY_VALUE(first_name) first_name
FROM `project.dataset.table`
GROUP BY age

如您所见,您只缺少聚合函数 - 它可以是任何值 - MAX、MIN 等。我选择 ANY_VALUE 作为示例

您可以使用以下示例中的一些简化的虚拟数据进行测试,使用上述方法

#standardSQL
WITH `project.dataset.table` AS (
  SELECT 'Thomas' first_name, 25 age UNION ALL
  SELECT 'Mike', 25 UNION ALL
  SELECT 'Thomas', 30 UNION ALL
  SELECT 'Mark', 40
)
SELECT ANY_VALUE(first_name) first_name
FROM `project.dataset.table`
GROUP BY age

结果

Row first_name   
1   Thomas   
2   Thomas   
3   Mark     

【讨论】:

谢谢,这正是我想要找到的。【参考方案2】:

您还必须将所有选定的列放在group by

 select first_name, last_name from 
`table` group by age,first_name, last_name

顺便说一句,在 8.0 版本的 mysql 之前是允许的,但从 8.0 开始是不允许的

但是在你的查询中没有聚合函数,所以你可以使用 distinct 而不是 group by

select distinct first_name, last_name from 
    `table`

【讨论】:

谢谢,请查看更新后的问题,其中使用 distinct 不起作用。 按名字和年龄分组【参考方案3】:

在 BigQuery 中,您应该使用窗口函数:

select t.*
from (select t.*, row_number() over (partition by age order by age) as seqnum
      from t
     ) t
where seqnum = 1;

这也适用于 MySQL 8+。

【讨论】:

最后,非常感谢,这就是我要找的。出于好奇,您能否解释一下为什么需要通过age 订购并获得row_number() @DavidL。 . .该标准要求order by 对应row_number()。虽然 BigQuery 没有,但我倾向于在使用该函数时包含 order by

以上是关于如何在 SQL 语句中获取非分组列(类似于 MySQL)的主要内容,如果未能解决你的问题,请参考以下文章

如何在 Java 中获取第一个非空值?

用于基于三个参数查找唯一行的 SQL 查询 - 类似于“在已排序的分组集中获取第一行”

SQL语句汇总——聚合函数分组子查询及组合查询

MySQL TIMESTAMP 列 - 按天分组

在sql中使用case语句根据某些条件对列进行分组

如何按一列的最大值获取SQL行,按另一列分组