Подзапрос MS SQL

#sql #sql-server #subquery #database-indexes

Вопрос:

Я новичок в этом, но я попытался выбрать или создать подзапрос, который вернет клиентам, купившим товар, который дороже, чем товар (в таблице), купленный товар.

Оператор/подзапрос select, который я создал, возвращает данные буквально всех в таблице, за исключением товара, даже цены ниже, чем у его товара, хотя я указал цены выше, чем у товара. Что, по-видимому, не так в моем подзапросе?

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

1. Примечание к дизайну: я бы предложил разработать отношения «многие ко многим», если вы когда-нибудь захотите, чтобы кто-то мог приобрести более 1 товара в заказе (что люди часто делают в реальном мире).

2. Возможно, я впервые вижу, чтобы кто-то использовал > ALL (...) это специально, а не просто как часть какого-то пустякового вопроса о непонятном синтаксисе SQL.

Ответ №1:

Похоже, вы могли бы использовать подзапрос, подобный следующему. Я предполагаю, что если бы Баданг купил несколько предметов, вы бы хотели, чтобы покупка была больше, чем их покупка по самой высокой стоимости:

 SELECT C.Cust_Name,
       I.ItemName,
       I.Price
FROM dbo.Customers C
     JOIN dbo.Orders O ON  C.CustomerID = O.CustomerID
     JOIN dbo.Items I ON O.ItemID = I.ItemID
WHERE I.Price > (SELECT MAX(Isq.Price)
                 FROM dbo.Customers Csq
                      JOIN dbo.Orders Osq ON Csq.CustomerID = Osq.CustomerID
                      JOIN dbo.Items Isq ON Osq.ItemID = Isq.ItemID
                 WHERE Csq.Cust_Name = 'Badang');
 

Ответ №2:

Немного другой способ думать об этом означает, что вам нужно только явно ссылаться на каждую таблицу один раз (это не удаляет их из плана).:

 DECLARE @cust_name varchar(50) = 'Badang';

;WITH x AS 
(
  SELECT c.Cust_Name,
         i.ItemName,
         i.Price,
         max_price = MAX(CASE WHEN Cust_Name = @cust_name THEN i.Price END)
                     OVER (PARTITION BY c.CustomerID)
  FROM dbo.Customers    AS c
  INNER JOIN dbo.Orders AS o ON c.CustomerID = o.CustomerID
  INNER JOIN dbo.Items  AS i ON o.ItemID = i.ItemID
)
SELECT Cust_Name, ItemName, Price FROM x WHERE Price > 
(
  SELECT max_price FROM x WHERE Cust_Name = @cust_name
);
 

Кроме того, ваши таблицы действительно должны иметь ключи и кластеризованные индексы; в своем текущем состоянии эти запросы пронизаны поиском RID.