如何在SQL聚合查询中获取分组第一条记录的描述字段值
实现分组求和并获取每组第一条记录的Description
当然可以实现这个需求!根据你使用的数据库系统不同,有几种靠谱的方法能达成目标,下面给你逐一拆解:
方法1:窗口函数(推荐,支持SQL Server、PostgreSQL、MySQL 8.0+等)
窗口函数是最灵活的方案,我们可以利用它给每组内的记录标记序号,再筛选出每组的第一条记录,同时结合聚合求和:
方式A:用ROW_NUMBER()标记后聚合
WITH RankedExpenses AS ( SELECT [Name], [Description], [Amount], -- 给每个Name分组内的记录编序号,这里用(SELECT NULL)表示不指定排序规则,取原表中最先出现的记录 -- 如果有明确的排序字段(比如记录创建时间CreatedDate),建议替换成该字段,结果更稳定 ROW_NUMBER() OVER (PARTITION BY [Name] ORDER BY (SELECT NULL)) AS RowNum FROM [dbo].[Expenses] ) SELECT [Name], -- 取每组序号为1的Description MAX(CASE WHEN RowNum = 1 THEN [Description] END) AS [Description], SUM([Amount]) AS [Amount] FROM RankedExpenses GROUP BY [Name];
方式B:用FIRST_VALUE()直接获取第一条值
更简洁的写法,直接用FIRST_VALUE()窗口函数提取每组的第一条Description:
SELECT DISTINCT [Name], FIRST_VALUE([Description]) OVER (PARTITION BY [Name] ORDER BY (SELECT NULL)) AS [Description], SUM([Amount]) OVER (PARTITION BY [Name]) AS [Amount] FROM [dbo].[Expenses];
方法2:SQL Server专属写法(TOP 1 WITH TIES)
如果你用的是SQL Server,还可以用这个更简洁的技巧:
SELECT TOP 1 WITH TIES [Name], [Description], SUM([Amount]) OVER (PARTITION BY [Name]) AS [Amount] FROM [dbo].[Expenses] ORDER BY ROW_NUMBER() OVER (PARTITION BY [Name] ORDER BY (SELECT NULL));
方法3:关联子查询(兼容性拉满,适合老版本数据库)
如果你的数据库不支持窗口函数(比如MySQL 5.x),关联子查询是个稳妥的选择:
SQL Server版本
SELECT e.[Name], -- 子查询获取当前Name组的第一条Description (SELECT TOP 1 [Description] FROM [dbo].[Expenses] WHERE [Name] = e.[Name]) AS [Description], SUM(e.[Amount]) AS [Amount] FROM [dbo].[Expenses] e GROUP BY e.[Name];
MySQL/PostgreSQL版本
SELECT e.[Name], -- 用LIMIT 1替代TOP 1 (SELECT [Description] FROM [dbo].[Expenses] WHERE [Name] = e.[Name] LIMIT 1) AS [Description], SUM(e.[Amount]) AS [Amount] FROM [dbo].[Expenses] e GROUP BY e.[Name];
重要提示
如果原表中没有明确的排序字段(比如记录插入时间),仅靠“原表第一条记录”的定义是不稳定的——数据库的存储顺序可能会因为索引、数据维护等操作发生变化。建议尽量指定一个排序字段(比如CreatedDate)来确保每次都能拿到你预期的那条Description。
内容的提问来源于stack exchange,提问作者Philip Stratford
相关产品推荐
相关产品推荐

