У меня есть таблица в хранилище данных, которая выглядит следующим образом:

TicketNbr  Cpn  Start   End
279211      1   CHS     JFK  
295946      1   JFK     TPA  
279211      2   JFK     TPA  
234916      1   JFK     CHS
284916      1   JFK     CHS
279211      3   TPA     JFK
279211      4   JFK     CHS

Я хочу вернуть строки с TicketNbr = 279211, и я хочу только вернуть строки, которые имеют минимальное и максимальное значение Cpn. Так что из этой таблицы я хочу вернуться

TicketNbr  Cpn  Start   End       
279211      1   CHS     JFK
279211      4   JFK     CHS

Я не очень опытный в SQL, поэтому я попытался

SELECT
TicketNbr,
MIN(Cpn),
Start AS [StartCity],
End AS [EndCity]
FROM TKTExchange AS T
GROUP BY TicketNbr
WHERE TicketNbr = '279211'
LEFT JOIN
    (SELECT  
    MAX(Cpn),
    Start AS [StartCity],
        End AS [EndCity]
    FROM TKTExchange
    GROUP BY TicketNbr) AS GT
ON T.TicketNbr = GT.TicketNbr

Но GROUPBY не работает в этом контексте. Как я мог сделать это?

3
td.mart 1 Май 2019 в 21:22

4 ответа

Лучший ответ

С group by TicketNbr вы можете получить минимальные и максимальные значения, которые вам нужны, и затем присоединиться к таблице. Если есть еще строки с одинаковыми Cpn, они все будут возвращены:

select t.* from TKTExchange t
inner join (
  select TicketNbr, min(Cpn) mincpn, max(Cpn) maxcpn
  from TKTExchange
  group by TicketNbr
) g on g.TicketNbr = t.TicketNbr and t.Cpn in (g.mincpn, g.maxcpn)

Вы можете добавить условия, такие как:

where t.TicketNbr = 279211
1
forpas 1 Май 2019 в 18:29

Другой вариант - использовать WITH TIES совместно с row_number()

Пример

Select Top 1 With Ties * 
 From  YourTable
 Where TicketNbr = 279211 
 Order By Row_Number() over (Partition By [TicketNbr] Order by Cpn Desc)
         *Row_Number() over (Partition By [TicketNbr] Order by Cpn Asc) 

Возврат

TicketNbr   Cpn Start   End
279211      1   CHS     JFK
279211      4   JFK     CHS

dbFiddle

2
John Cappelletti 1 Май 2019 в 18:30

Немного отличающийся от других метод, использующий CTE и оконные функции:

WITH VTE AS (
    SELECT *,
           MIN(Cpn) OVER (PARTITION BY TicketNbr) AS MinCpn,
           MAX(Cpn) OVER (PARTITION BY TicketNbr) AS MaxCpn
    FROM (VALUES(279211,1,'CHS','JFK'),  
                (295946,1,'JFK','TPA'),  
                (279211,2,'JFK','TPA'),  
                (234916,1,'JFK','CHS'),
                (284916,1,'JFK','CHS'),
                (279211,3,'TPA','JFK'),
                (279211,4,'JFK','CHS')) V(TicketNbr,Cpn,[Start],[End])
    WHERE V.TicketNbr = 279211)
SELECT V.Cpn,
       V.Cpn,
       V.[Start],
       V.[End]
FROM VTE V
WHERE V.Cpn = V.MinCpn
   OR V.Cpn = V.MaxCpn;
1
Larnu 1 Май 2019 в 18:32

Один из вариантов - выбрать верхнюю и нижнюю записи, а затем UNION объединить их в один набор данных. Такие как:

SELECT * FROM (SELECT TOP 1
     [TicketNbr]
    ,[Cpn]
    ,[Start]
    ,[End]
FROM [TKTExchange]
WHERE
    [TicketNbr] = '279211'
ORDER BY
    [Cpn] ASC) AS [A]

UNION

SELECT * FROM (SELECT TOP 1
     [TicketNbr]
    ,[Cpn]
    ,[Start]
    ,[End]
FROM [TKTExchange]
WHERE
    [TicketNbr] = '279211'
ORDER BY
    [Cpn] DESC) AS [B]
0
DBro 1 Май 2019 в 18:43