Я буду использовать конкретный, но гипотетический пример.
Каждый заказ обычно имеет только одну позицию :
Заказы:
OrderGUID OrderNumber
========= ============
{FFB2...} STL-7442-1
{3EC6...} MPT-9931-8A
Позиции:
LineItemGUID Order ID Quantity Description
============ ======== ======== =================================
{098FBE3...} 1 7 prefabulated amulite
{1609B09...} 2 32 spurving bearing
Но иногда будет заказ с двумя позициями:
LineItemID Order ID Quantity Description
========== ======== ======== =================================
{A58A1...} 6,784,329 5 pentametric fan
{0E9BC...} 6,784,329 5 differential girdlespring
Обычно при отображении заказов пользователю:
SELECT Orders.OrderNumber, LineItems.Quantity, LineItems.Description
FROM Orders
INNER JOIN LineItems
ON Orders.OrderID = LineItems.OrderID
Я хочу показать один элемент в заказе. Но с этим время от времени заказа , содержащие два (или более) элементов, заказы будут появляться быть продублированы :
OrderNumber Quantity Description
=========== ======== ====================
STL-7442-1 7 prefabulated amulite
MPT-9931-8A 32 spurving bearing
KSG-0619-81 5 panametric fan
KSG-0619-81 5 differential girdlespring
Я действительно хочу, чтобы SQL Server просто выбрал один , так как он будет достаточно хорош :
OrderNumber Quantity Description
=========== ======== ====================
STL-7442-1 7 prefabulated amulite
MPT-9931-8A 32 differential girdlespring
KSG-0619-81 5 panametric fan
Если я предприму приключение, я мог бы показать пользователю многоточие, чтобы указать, что их больше одного:
OrderNumber Quantity Description
=========== ======== ====================
STL-7442-1 7 prefabulated amulite
MPT-9931-8A 32 differential girdlespring
KSG-0619-81 5 panametric fan, ...
Так что вопрос в том, как
- устранить "дублирующиеся" строки
- только присоединиться к одной из строк, чтобы избежать дублирования
Первая попытка
Моей первой наивной попыткой было присоединиться только к позициям " TOP 1 ":
SELECT Orders.OrderNumber, LineItems.Quantity, LineItems.Description
FROM Orders
INNER JOIN (
SELECT TOP 1 LineItems.Quantity, LineItems.Description
FROM LineItems
WHERE LineItems.OrderID = Orders.OrderID) LineItems2
ON 1=1
Но это дает ошибку:
Столбец или префикс «Заказы» не
совпадает с именем таблицы или псевдонимом,
используемым в запросе.
Предположительно, потому что внутренний выбор не видит внешнюю таблицу.
источник
group by
?group by
, потребуется перечислить все остальные столбцы, за исключением того, где вы не хотите дубликатов. ИсточникОтветы:
В SQL Server 2005 и выше вы можете просто заменить
INNER JOIN
наCROSS APPLY
:Обратите внимание, что
TOP 1
безORDER BY
не является детерминированным: в этом запросе вы получите одну позицию на заказ, но не определено, какой она будет.Многократные вызовы запроса могут дать вам разные позиции для одного и того же заказа, даже если базовый уровень не изменился.
Если вы хотите детерминированный порядок, вы должны добавить
ORDER BY
предложение к самому внутреннему запросу.источник
CROSS APPLY
вместоINNER JOIN
иOUTER APPLY
вместоLEFT JOIN
(так же, какLEFT OUTER JOIN
).Я знаю, что на этот вопрос недавно был дан ответ, но при работе с большими наборами данных вложенные запросы могут быть дорогостоящими. Вот другое решение, где вложенный запрос будет выполняться только один раз, а не для каждой возвращаемой строки.
источник
Вы могли бы сделать:
Это требует наличия индекса (или первичного ключа) и включения
LineItems.LineItemID
индекса,LineItems.OrderID
или он будет медленным.источник
LineItems.LineItemID = null
и удаляет левые порядки объектов из результата.Ответ @Quassnoi хорош, в некоторых случаях (особенно если внешняя таблица большая), более эффективный запрос может быть с использованием оконных функций, например:
Иногда вам просто нужно проверить, какой запрос дает лучшую производительность.
источник
Другой подход, использующий общее табличное выражение:
или, в конце концов, может быть, вы хотите показать все соединенные строки?
Разделенная запятыми версия здесь:
источник
Начиная с SQL Server 2012 и далее, я думаю, что это поможет:
источник
Коррелированные подзапросы - это подзапросы, которые зависят от внешнего запроса. Это как цикл for в SQL. Подзапрос будет выполняться один раз для каждой строки во внешнем запросе:
источник
РЕДАКТИРОВАТЬ: не имеет значения, у Quassnoi есть лучший ответ.
Для SQL2K, что-то вроде этого:
источник
Мой любимый способ выполнения этого запроса - с предложением «не существует». Я считаю, что это самый эффективный способ выполнить такой запрос:
Но я не проверял этот метод против других методов, предложенных здесь.
источник
Попробовал крестик, работает приятно, но занимает немного дольше. Скорректированы столбцы строк, чтобы иметь максимум и добавлена группа, которая сохраняла скорость и отбрасывала дополнительную запись.
Вот скорректированный запрос:
источник
попробуй это
источник