Получить значение из первой записи в группе в совокупном запросе - PullRequest
0 голосов
/ 16 мая 2018

Рассмотрим следующие смехотворно упрощенные Расходы Таблица базы данных:

|------------------|--------------|--------|
|       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  |
|------------------|--------------|--------|

Это, очевидно, не фактические данные, с которыми я работаю, но мне интересно, возможно ли это сделать?

Ответы [ 3 ]

0 голосов
/ 16 мая 2018

Не существует такой вещи, как первая запись, поскольку таблицы 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_VALUE():

SELECT DISTINCT Name,
       FIRST_VALUE(Description) OVER (PARTITION BY name ORDER BY ?), 
       SUM(Amount) OVER (PARTITION BY name)
FROM dbo.Expenses;

. Используется FIRST_VALUE(), который доступен как аналитическая функция, но не оконная функция.

0 голосов
/ 16 мая 2018

Вы также можете использовать оконные функции -

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
0 голосов
/ 16 мая 2018

Использование subquery:

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]
...