Предложение EXISTS ISSUE с предложением TOP в подзапросе - PullRequest
0 голосов
/ 20 февраля 2020

У меня есть подзапрос запроса ниже (Цель поиска - поиск 2 лучших заказов из таблицы заказов, у которых freight_charges = 2 и получение клиентов этих заказов)

  1. Рабочий запрос с предложением IN
    SELECT *
    FROM Customers C
    WHERE C.CUST_ID IN (
      SELECT TOP 2 CUST_ID
      FROM Orders O
      where FREIGHT_CHARGES = 2
    ) 

Однако я хочу преобразовать предложение IN в более эффективное предложение EXISTS

Код не работает с существующим предложением
    SELECT *
    FROM Customers C
    WHERE EXISTS (
        SELECT TOP 2 CUST_ID
        FROM Orders O
        where FREIGHT_CHARGES = 2 AND C.CUST_ID = O.CUST_ID
    )

В случае второго запроса я не получаю верхние 2 cust_id, НО все записи.

Пожалуйста, дайте мне знать любую реализацию, чтобы получить желаемый результат.

Отредактировано: Использование INNER JOIN, как предлагается в ответах. Я могу получить правильный результат. Однако, поскольку я не хочу извлекать какие-либо записи из таблицы Orders, я подумал, что существует лучший подход к производительности.

    SELECT C.*
    FROM Customers C
    INNER JOIN (
      SELECT TOP 2 CUST_ID
      FROM Orders 
      where FREIGHT_CHARGES = 2
    ) O ON C.CUST_ID=O.CUST_ID

Ответы [ 4 ]

0 голосов
/ 20 февраля 2020
   SELECT Top 2 *
    FROM Customers as C
    WHERE EXISTS (
        SELECT O.CUST_ID
        FROM Orders as O
        where FREIGHT_CHARGES = 2 AND C.CUST_ID = O.CUST_ID
    )
0 голосов
/ 20 февраля 2020

Я могу предложить вам go для INNER JOIN. Всегда рекомендуется избегать подзапросов, если это возможно, поскольку они выполняются для каждой строки из главной таблицы, потому что она находится в состоянии WHERE. Скорее, вы можете использовать простой INNER JOIN для получения желаемого результата.

Как и в вашем примере, вам просто нужно TOP 2 клиентов, имеющих значение FREIGHT_CHARGES до 2. Вы можете использовать запрос ниже, используя INNER JOIN.

SELECT
    TOP 2
    C.*
FROM Customers C
INNER JOIN Orders O ON C.CUST_ID = O.CUST_ID
WHERE O.FREIGHT_CHARGES = 2
ORDER BY C.CUST_ID -- Use 'ORDER BY' clause if 'C.CUST_ID' column does not have clustered index or you can use any other column

Пожалуйста, дайте мне знать ваш отзыв.

0 голосов
/ 20 февраля 2020

Оператор EXISTS - это логический оператор, который позволяет проверить, возвращает ли подзапрос какую-либо строку. Оператор EXISTS возвращает TRUE, если подзапрос возвращает хотя бы одну или несколько строк.

Итак, поскольку каждая строка в таблице Order с FREIGHT_CHARGES = 2 будет возвращать TRUE для оператора EXISTS (не имеет значения, если это TOP 2, 1 будет достаточно) результат включает в себя все записи в таблице «Клиенты» с соответствующими CUST_ID в «Заказах».

В вашем случае EXISTS не будет хорошим выбором для вас.

Пожалуйста, проверьте эту ссылку: https://www.sqlservertutorial.net/sql-server-basics/sql-server-exists/

0 голосов
/ 20 февраля 2020

Если вы смешаете EXISTS с TOP, нет никакой разницы, чем вы используете его без TOP, потому что EXISTS"Возвращает TRUE, если подзапрос содержит какие-либо строки".

В вашем случае вы можете проверить запросы:

SELECT *
FROM Customers C
  WHERE EXISTS (
    SELECT 1
    FROM Orders O
    JOIN Orders O2
      ON O.FREIGHT_CHARGES = O2.FREIGHT_CHARGES 
      AND O.CUST_ID = O.CUST_ID
      AND O.ID <> O2.ID
    where O.FREIGHT_CHARGES = 2 AND C.CUST_ID = O.CUST_ID
   )

Или

SELECT *
FROM Customers C
WHERE EXISTS (
    SELECT 1
    FROM Orders O
    where FREIGHT_CHARGES = 2 AND C.CUST_ID = O.CUST_ID
    GROUP BY FREIGHT_CHARGES, CUST_ID
    HAVING COUNT(1) > 1
)

Вы должны проверить, какой из них лучше в вашем случае

...