Sql 从聚合查询中组中的第一条记录获取值

Sql 从聚合查询中组中的第一条记录获取值,sql,sql-server,aggregate-functions,Sql,Sql Server,Aggregate Functions,考虑以下可笑的简化费用数据库表: |------------------|--------------|--------| | Name | Description | Amount | |------------------|--------------|--------| | John Smith | Hotel | £100 | | John Smith | Evening meal | £30 | | Clai

考虑以下可笑的简化费用数据库表:

|------------------|--------------|--------|
|       Name       | Description  | Amount |
|------------------|--------------|--------|
|    John Smith    |    Hotel     |  £100  |
|    John Smith    | Evening meal |   £30  |
|   Claire Jones   |    Lunch     |   £20  |
|    John Smith    |    Travel    |   £80  |
|   Claire Jones   |    Hotel     |  £150  |
|------------------|--------------|--------|
使用SQL

SELECT [Name], SUM([Amount])
FROM [dbo].[Expenses]
GROUP BY [Name]
我可以得到结果

|------------------|--------|
|    John Smith    |  £210  |
|   Claire Jones   |  £170  |
|------------------|--------|
但是,我想知道如何才能获得相同的结果,但需要一个额外的描述列,该列仅显示聚合组中第一条记录的基表描述列中的值。例如:

|------------------|--------------|--------|
|       Name       | Description  | Amount |
|------------------|--------------|--------|
|    John Smith    |    Hotel     |  £210  |
|   Claire Jones   |    Lunch     |  £170  |
|------------------|--------------|--------|

这显然不是我正在处理的实际数据,但我想知道是否有可能做到这一点?

使用
子查询

SELECT [Name], SUM([Amount]) Amount,
       (SELECT TOP 1 Description  
        FROM [dbo].[Expenses] 
        WHERE Name = e.Name 
        ORDER BY Name) Description
FROM [dbo].[Expenses] e
GROUP BY [Name]

使用
子查询

SELECT [Name], SUM([Amount]) Amount,
       (SELECT TOP 1 Description  
        FROM [dbo].[Expenses] 
        WHERE Name = e.Name 
        ORDER BY Name) Description
FROM [dbo].[Expenses] e
GROUP BY [Name]

没有第一条记录,因为SQL表表示无序数据

因此,可以在列中使用排序。在您的情况下,这可能是:

SELECT Name, MIN(Description), SUM(Amount)
FROM dbo.Expenses
GROUP BY Name;
如果有排序列,则可以使用条件聚合:

SELECT Name, 
       MAX(CASE WHEN seqnum = 1 THEN Description END),
       SUM(Amount)
FROM (SELECT e.*,
             ROW_NUMBER() OVER (PARTITION BY Name ORDER BY ?) as seqnum
      FROM dbo.Expenses e
     ) e
GROUP BY Name;
是排序列的占位符

使用
第一个值()
还有另一种相当神秘的方法:


这使用了
FIRST\u VALUE()
,该函数可用作分析函数,但不是窗口函数。

没有第一条记录,因为SQL表表示无序数据

因此,可以在列中使用排序。在您的情况下,这可能是:

SELECT Name, MIN(Description), SUM(Amount)
FROM dbo.Expenses
GROUP BY Name;
如果有排序列,则可以使用条件聚合:

SELECT Name, 
       MAX(CASE WHEN seqnum = 1 THEN Description END),
       SUM(Amount)
FROM (SELECT e.*,
             ROW_NUMBER() OVER (PARTITION BY Name ORDER BY ?) as seqnum
      FROM dbo.Expenses e
     ) e
GROUP BY Name;
是排序列的占位符

使用
第一个值()
还有另一种相当神秘的方法:


这将使用作为分析函数提供的
第一个值()
,但不是窗口函数。

您也可以使用窗口函数-

SELECT [Name],
    SUM([Amount]) OVER (PARTITION BY [Name]) as total_amount,
    ROW_NUMBER() OVER (PARTITION BY [Name] ORDER BY some_column) as row_num
  FROM [dbo].[Expenses]
  WHERE row_num = 1

您还可以使用窗口功能-

SELECT [Name],
    SUM([Amount]) OVER (PARTITION BY [Name]) as total_amount,
    ROW_NUMBER() OVER (PARTITION BY [Name] ORDER BY some_column) as row_num
  FROM [dbo].[Expenses]
  WHERE row_num = 1