Функция ROW_NUMBER
в CTE - способ сделать это. Например:
DECLARE @mytab TABLE (A INT, B INT, C INT)
INSERT INTO @mytab ( A, B, C ) VALUES (1, 1, 1)
INSERT INTO @mytab ( A, B, C ) VALUES (1, 1, 2)
INSERT INTO @mytab ( A, B, C ) VALUES (1, 2, 1)
INSERT INTO @mytab ( A, B, C ) VALUES (1, 3, 1)
INSERT INTO @mytab ( A, B, C ) VALUES (2, 2, 2)
INSERT INTO @mytab ( A, B, C ) VALUES (3, 3, 1)
INSERT INTO @mytab ( A, B, C ) VALUES (3, 3, 2)
INSERT INTO @mytab ( A, B, C ) VALUES (3, 3, 3)
;WITH numbered AS
(
SELECT *, rn=ROW_NUMBER() OVER (PARTITION BY A ORDER BY B, C)
FROM @mytab AS m
)
SELECT *
FROM numbered
WHERE rn=1
Как я уже упоминал в своем комментарии к HLGEM и Филипу Келли, их простое использование агрегатной функции не обязательно возвращает одну "твердую" запись для каждой группы A; вместо этого он может возвращать значения столбцов из множества отдельных строк, все сшитые вместе, как если бы они были одной записью. Например, если это таблица PERSON, в которой PersonID представляет собой столбец «A», а отдельные записи о контактах (скажем, «Домой» и «Word»), вы можете вернуть свой город, но почтовый индекс его офиса это явно напрашивается на неприятности.
Использование ROW_NUMBER в сочетании с CTE здесь немного сложнее для начала, потому что синтаксис неудобен. Но это становится довольно распространенным паттерном, так что лучше узнать его.
В моем примере я определил CTE, который привязывает дополнительный столбец rn
(обозначающий «номер строки») к таблице, которая сама группируется по столбцу A. A SELECT
для этого результата, отфильтровывая только те, которые имеют номер строки 1 (т. Е. Первую найденную запись для этого значения A), возвращает «сплошную» запись для каждой группы A - в моем примере выше вы Обязательно получите рабочий адрес или Home, но не элементы обоих вместе.