Sql 基于单个字段聚合整行,而无需查询源两次或使用CTE?

Sql 基于单个字段聚合整行,而无需查询源两次或使用CTE?,sql,aggregate-functions,teradata,greatest-n-per-group,Sql,Aggregate Functions,Teradata,Greatest N Per Group,假设我有下表: +--------+--------+--------+ | field1 | field2 | field3 | +--------+--------+--------+ | a | a | 1 | | a | b | 2 | | a | c | 3 | | b | a | 1 | | b | b | 2 | | c |

假设我有下表:

+--------+--------+--------+
| field1 | field2 | field3 |
+--------+--------+--------+
| a      | a      |      1 |
| a      | b      |      2 |
| a      | c      |      3 |
| b      | a      |      1 |
| b      | b      |      2 |
| c      | b      |      2 |
| c      | b      |      3 |
+--------+--------+--------+
我只想选择field3为最小值的行,因此仅选择以下行:

+--------+--------+--------+
| field1 | field2 | field3 |
+--------+--------+--------+
| a      | a      |      1 |
| b      | a      |      1 |
| c      | b      |      2 |
+--------+--------+--------+
最流行的解决方案是两次查询源,一次直接查询,然后连接到子查询,在子查询中再次查询源,然后进行聚合。然而,由于我的数据源实际上是一个派生表/子查询本身,因此我必须在我的SQL中复制子查询,这很难看。另一个选项是与CTE一起使用并重用子查询,这很好,但是我正在使用的数据库Teradata在视图中不支持CTE,尽管它在宏中支持CTE,而宏现在不支持CTE

因此,在标准SQL中,是否可以只使用聚合中的一个字段将多个记录分组到一个记录中,而无需查询源两次或使用CTE?

如果没有其他行具有相同的field1值但具有更低的field3值,则使用NOT EXISTS返回一行:

select * from table t1
where not exists (select 1 from table t2
                  where t2.field1 = t1.field1
                    and t2.field3 < t1.field3)

这可以通过使用窗口功能实现:

select *
from (
  select column_1, column_2, column_3, 
         min(column_3) over (partition by column_1) as min_col_3
  from the_table
) t
where column_3 = min_col_3;
以上是标准SQL,我相信Teradata也支持窗口函数

派生表是必需的,因为您不能在where子句中引用列别名,至少在标准SQL中不能。 我认为应该使用Qualife运算符,但由于我从未使用过它,我不确定:

select *
from the_table
qualify min(column_3) over (partition by column_1) = column_3;

关于field1的最低要求?@jarlh是的。第二个表中的结果显示了我希望看到的结果。我可以想象这也是OP希望避免的子查询。@TabAlleman。我不想在同一个主查询中引用源代码两次,这正是此SQL所做的。我认为这是在QUIFITE子句中按列1划分的mincolumn_3。我不敢相信我没有想到这一点,现在我想起我已经在其他地方这样做了。谢谢你敲了我的头!我对窗口函数并没有太多的了解,所以我一直在使用模板SQL,比如按主播字段按分区排序按递增字段排序。这是可行的,但我仍然需要了解窗口函数,我甚至不知道它们是如何被调用的。您也可以使用RANK来代替MIN,这取决于实际数据,其中一个可能更有效:按列_1顺序按列_3=1限定分区上的RANK;