T-SQL » ЛЮБОЙ (подзапрос)»

#sql-server

#sql-сервер

Вопрос:

У меня вопрос о Any-Operator .

В Technet говорится

Например, следующий запрос находит клиентов, расположенных на территории, не охваченной никакими продавцами.

 Use AdventureWorks2008R2;
GO
SELECT
    CustomerID
FROM
    Sales.Customer
WHERE
    TerritoryID <> ANY
    (
        SELECT
            TerritoryID
        FROM
            Sales.SalesPerson
    );
  

Далее

Результаты включают всех клиентов, кроме тех, чьи территории продаж равны НУЛЮ, поскольку каждая территория, назначенная клиенту, покрывается продавцом. Внутренний запрос находит все территории продаж, охваченные продавцами, а затем для каждой территории внешний запрос находит клиентов, которых нет ни на одной.

Но этот запрос возвращает всех клиентов. Я обновил идентификатор территории клиентов до значения, которого нет у sales.person, но все же этот запрос возвращает всех клиентов вместо того, которого я ожидал..

Я что-то упускаю? Может быть, эта статья о technet просто неверна? https://technet.microsoft.com/de-de/library/ms187074 (v=sql.105).aspx (немецкий)

Есть один клиент с TerritoryID = 13

Результат внутреннего запроса (ВЫБЕРИТЕ TerritoryID ИЗ Sales.Продавец) : 4 2 4 3 6 5 1 4 6 1 1 6 9 1 8 10 7

И в таблице продаж.Customer — это строка с CustomerID = 13, которая не охвачена продавцом..

Комментарии:

1. Английская версия ( technet.microsoft.com/en-US/library/ms187074 (v = sql.105).aspx ) — который, как мы можем предположить, является каноническим, гласит (со ссылкой на опубликованный вами код): «Результаты включают всех клиентов, кроме тех, чьи территории продаж равны НУЛЮ, потому что каждая территория, назначенная клиенту, покрытаспециалистом по продажам.» — вы уверены, что ваш запрос возвращает каждого клиента или просто клиента с очень ненулевой территорией? Помните, что операторы сравнения не работают интуитивно со NULL значениями.

2. У вас не равно НИ ОДНОЙ строке. проще говоря, если в SalesPerson есть хотя бы 2 строки, вы получите все строки обратно. потому что одно значение может совпадать, а другое — нет. 🙂 Для чего-то подобного, чтобы найти дубликаты, я бы предпочел использовать левое соединение или exists .

3. » вы уверены, что ваш запрос возвращает каждого клиента» — да.

4. в нем говорится: «Внутренний запрос находит все территории продаж, охваченные продавцами, а затем для каждой территории внешний запрос находит клиентов, которых нет в одном» — и этот внешний запрос показывает каждого клиента (но у них есть covered TerritoryID .. и это то, что я не понимаю

Ответ №1:

 create table #t1
(
id int
)

insert into #t1
values(1),(2),(3)
  

Как вы можете видеть, T1 имеет три значения

теперь давайте посмотрим, как работает Any

Когда ‘равно ‘ используется с любым, это работает как В

 select * from #t1 where id=
any(select 0)--no result
  

когда Any используется с > или <> , Any означает получение всех значений, которые больше минимального значения

 select * from #t1 where id<>
any(select 1)--2,3

select * from #t1 where id<>
any(select 0)--1,2,3
  

Если ваш подзапрос возвращает одно значение, внешний запрос попытается получить значения, которые больше, чем внутренний запрос

Комментарии:

1. Я понимаю ваш пример 🙂 Но я не понимаю, что в нем говорится: «Например, следующий запрос находит клиентов, расположенных на территории, не охваченной никакими продавцами.». . technet.microsoft.com/en-us/library/ms187074 (v=sql.105).aspx

2. . у меня нет этой конкретной базы данных для тестирования. пожалуйста, обновите qstn с помощью результата внутреннего запроса

Ответ №2:

<> ANY означает любые продажи.Клиент с идентификатором территории, который больше или меньше любого из идентификаторов территории в Sales.SalesPerson

so TerritoryID = 13 больше, чем все или ваши примеры (4 2 4 3 6 5 1 4 6 1 1 6 9 1 8 10 7) , поэтому он включен.

<> ALL это эквивалент NOT IN so, с которым вы путаете <> ANY

Посмотрите на <> ANY as, если в наборе есть какие-либо записи, которые не равны параметру quailifier, затем включите его.

Ответ №3:

Следующий запрос имеет тот же результат:

 SELECT CustomerID FROM Sales.Customer
WHERE TerritoryID NOT IN (SELECT TerritoryID FROM Sales.SalesPerson)
  

Комментарии:

1. OP пытается понять, почему его оператор ведет себя определенным образом — это не помогает ответить на этот вопрос.