Самый гибкий способ написать это, не требующий коррелированного подзапроса, - это использовать ROW_NUMBER
(только для SQL Server 2005+):
;WITH Names_CTE AS
(
SELECT
ID, RefNumber, Forename, Surname,
ROW_NUMBER() OVER (PARTITION BY RefNumber ORDER BY ID) AS RowNum
FROM Names
)
SELECT o.RefNumber, o.Charge, o.IssueDate, n.Forename, n.Surname
FROM Orders o
[INNER|LEFT] JOIN Names_CTE n
ON n.RefNumber = o.RefNumber
WHERE n.RowNum = 1
Обратите внимание, что ROW_NUMBER
не всегда наиболее эффективен, если вместо него можно использовать MIN/MAX
, просто проще всего писать.
Если вы используете SQL 2000 или он недостаточно эффективен, вы можете попробовать запрос MIN
или MAX
:
SELECT o.RefNumber, o.Charge, o.IssueDate, n.Forename, n.Surname
FROM Orders o
[INNER|LEFT] JOIN
(
SELECT RefNumber, MIN(ID) AS MinID
FROM Names
GROUP BY RefNumber
) m
ON m.RefNumber = o.RefNumber
[INNER|LEFT] JOIN Names n
ON n.ID = m.MinID
Иногда это на самом деле быстрее, это во многом зависит от используемой стратегии индексации.
(Правка - получаются строки с наименьшим ID, который в большинстве случаев будет быстрее, чем наибольший ID. Если вам нужен самый высокий, измените первый запрос на ORDER BY ID DESC
и второй запрос для использования MAX
вместо MIN
).