SQL Server: расширено наибольшее число групп - PullRequest
4 голосов
/ 20 марта 2012

Мой стол выглядит так:

A     B     C     D
1     1     1     1
1     1     3     2
1     1     0     4
1     1     2     1     
1     2     1     0
1     2     0     2
1     2     4     5   
2     1     5     3

Моя цель - для каждой пары A и B вывести значение в D, соответствующее MIN (C), и значение в D, соответствующее MAX (C). Выход должен быть

A    B    D at MIN(C)    D at MAX(C)
1    1    4              2
1    2    2              5
2    1    3              3

Я знаю, что для извлечения MIN (C) и MAX (C) я просто делаю:

SELECT A, B, MIN(C) as "minC", MAX(C) as "maxC"
FROM Table
GROUP BY A, B
ORDER BY A, B

Мой вопрос: как взять с собой колонку D для поездки? Если я включу его в предложения SELECT и GROUP BY, он будет генерировать MIN (C) и MAX (C) для каждого D, а это не то, что мне нужно. Более того, мне даже не нужно выводить MIN (C) и MAX (C). D - это все, что мне нужно.

Базовая схема, представленная в Выбор SQL только строк с максимальным значением для столбца , похоже, не справляется с этим случаем.

Заранее спасибо!

Ответы [ 2 ]

4 голосов
/ 20 марта 2012

Ваш запрос может выглядеть примерно так:

;with C as
(
  select A, B, C, D,
         row_number() over(partition by A, B order by C asc) as rn1,
         row_number() over(partition by A, B order by C desc) as rn2
  from YourTable
)
select C1.A, C1.B, C1.D as "D at MIN(C)", C2.D as "D at MAX(C)"
from C as C1
  inner join C as C2
    on C1.A = C2.A and
       C1.B = C2.B
where C1.rn1 = 1 and
      C2.rn2 = 1

Первая часть - это общее табличное выражение (CTE) , которое инкапсулирует запрос, который можно использовать позже в основном запросе.,Он использует row_number () для перечисления строк в каждом разделе.rn1 упорядочено по C asc, поэтому rn1 = 1 для минимального значения C и rn2 упорядочено по C desc, а это означает, что rn2 = 1 для максимального значения C.Основной запрос - это два раза объединение CTE в столбцах A и B.Предложение where гарантирует, что мы получим только те строки, где rn1 и rn2 равны 1.

Вот рабочий пример, в котором вместо таблицы используется переменная таблицы @T.

declare @T table
(
  A int,
  B int,
  C int,
  D int
)

insert into @T values
(1,     1,     1,     1),
(1,     1,     3,     2),
(1,     1,     0,     4),
(1,     1,     2,     1),   
(1,     2,     1,     0),
(1,     2,     0,     2),
(1,     2,     4,     5), 
(2,     1,     5,     3)

;with C as
(
  select A, B, C, D,
         row_number() over(partition by A, B order by C asc) as rn1,
         row_number() over(partition by A, B order by C desc) as rn2
  from @T
)
select C1.A, C1.B, C1.D as "D at MIN(C)", C2.D as "D at MAX(C)"
from C as C1
  inner join C as C2
    on C1.A = C2.A and
       C1.B = C2.B
where C1.rn1 = 1 and
      C2.rn2 = 1
0 голосов
/ 20 марта 2012

Примерно так может работать:

SELECT A, B, MIN(C) as "minC", MAX(C) as "maxC", 
(SELECT TOP 1 D FROM Table [table2] WHERE table1.A = table2.A AND table1.B = table2.B AND MIN(table1.C) = table2.C) As [D]
FROM Table [table1]
GROUP BY A, B
ORDER BY A, B
...