Подзапрос SQL Server вернул более 1 значения. Это недопустимо, если подзапрос следует =,! =, <, <=,>,> = - PullRequest
67 голосов
/ 16 апреля 2010

Я запускаю следующий запрос:

SELECT 
   orderdetails.sku,
   orderdetails.mf_item_number,
   orderdetails.qty,
   orderdetails.price,
   supplier.supplierid,
   supplier.suppliername,
   supplier.dropshipfees,
   cost = (SELECT supplier_item.price
           FROM   supplier_item,
                  orderdetails,
                  supplier
           WHERE  supplier_item.sku = orderdetails.sku
                  AND supplier_item.supplierid = supplier.supplierid)
FROM   orderdetails,
       supplier,
       group_master
WHERE  invoiceid = '339740'
       AND orderdetails.mfr_id = supplier.supplierid
       AND group_master.sku = orderdetails.sku  

Я получаю следующую ошибку:

Сообщение 512, Уровень 16, Состояние 1, Строка 2 Подзапрос вернул более 1 значения. Это недопустимо, если подзапрос следует =,! =, <, <=,>,> = Или когда подзапрос используется в качестве выражения.

Есть идеи?

Ответы [ 10 ]

41 голосов
/ 16 апреля 2010

Попробуйте это:

SELECT
    od.Sku,
    od.mf_item_number,
    od.Qty,
    od.Price,
    s.SupplierId,
    s.SupplierName,
    s.DropShipFees,
    si.Price as cost
FROM
    OrderDetails od
    INNER JOIN Supplier s on s.SupplierId = od.Mfr_ID
    INNER JOIN Group_Master gm on gm.Sku = od.Sku
    INNER JOIN Supplier_Item si on si.SKU = od.Sku and si.SupplierId = s.SupplierID
WHERE
    od.invoiceid = '339740'

Это вернет несколько одинаковых строк, кроме столбца cost. Посмотрите на различные значения затрат, которые возвращаются, и выясните, что является причиной различных значений. Затем спросите кого-нибудь, какое значение стоимости оно хочет, и добавьте в запрос критерии, которые выберут эту стоимость.

37 голосов
/ 12 октября 2010

Проверьте, есть ли в таблице триггеры, к которым вы пытаетесь выполнить запросы. Иногда они могут выдать эту ошибку, когда пытаются запустить триггер обновления / выбора / вставки, который находится в таблице.

Вы можете изменить запрос, чтобы отключить его, а затем включить триггер, если триггер НЕ выполняется для любого запроса, который вы пытаетесь запустить.

ALTER TABLE your_table DISABLE TRIGGER [the_trigger_name]

UPDATE    your_table
SET     Gender = 'Female'
WHERE     (Gender = 'Male')

ALTER TABLE your_table ENABLE TRIGGER [the_trigger_name]
19 голосов
/ 11 сентября 2013
SELECT COLUMN 
    FROM TABLE 
WHERE columns_name
    IN ( SELECT COLUMN FROM TABLE WHERE columns_name = 'value');

примечание: когда мы используем подзапрос, мы должны сосредоточиться на точке

  1. если наш подзапрос возвращает одно значение, в этом случае мы используем (=,! =, <>, <,> ....)
  2. else (более одного значения) в этом случае мы используем (в, любом, всех, некоторых)
13 голосов
/ 16 апреля 2010
cost = Select Supplier_Item.Price from Supplier_Item,orderdetails,Supplier 
   where Supplier_Item.SKU=OrderDetails.Sku and 
      Supplier_Item.SupplierId=Supplier.SupplierID

Этот подзапрос возвращает несколько значений, SQL жалуется, потому что не может назначить несколько значений стоимости в одной записи.

Некоторые идеи:

  1. Исправьте данные так, чтобы существующий подзапрос возвратил только 1 запись
  2. Исправьте подзапрос так, чтобы он возвращал только одну запись
  3. Добавить топ 1 и упорядочить в подзапросе (неприятное решение, которое ненавидят администраторы баз данных, но оно "работает")
  4. Использование определенной пользователем функции для объединения результатов подзапроса в одну строку
10 голосов
/ 16 апреля 2010

Исправлено - перестать использовать коррелированные подзапросы и использовать вместо них объединения. Коррелированные подзапросы - это, по сути, курсоры, поскольку они заставляют запрос выполняться построчно, и его следует избегать.

Вам может понадобиться производная таблица в соединении, чтобы получить желаемое значение в поле, если вы хотите, чтобы соответствовала только одна запись, если вам нужны оба значения, тогда обычный join сделает это, но вы получите несколько записей для одного и того же идентификатора в наборе результатов. Если вы хотите только один, вам нужно решить, какой из них и сделать это в коде, вы можете использовать top 1 с order by, вы можете использовать max(), вы можете использовать min() и т. Д., В зависимости от каково ваше реальное требование к данным.

9 голосов
/ 17 апреля 2010

Либо ваши данные неверны, либо они не структурированы так, как вы думаете. Возможно, оба.

Чтобы доказать / опровергнуть эту гипотезу, выполните этот запрос:

SELECT * from
(
    SELECT count(*) as c, Supplier_Item.SKU
    FROM Supplier_Item
    INNER JOIN orderdetails
        ON Supplier_Item.sku = orderdetails.sku
    INNER JOIN Supplier
        ON Supplier_item.supplierID = Supplier.SupplierID
    GROUP BY Supplier_Item.SKU
) x
WHERE c > 1
ORDER BY c DESC

Если это возвращает только несколько строк, то ваши данные неверны . Если он возвращает лотов строк, то ваши данные не структурированы так, как вы думаете. (Если он возвращает ноль строк, Я ошибаюсь. )

Я предполагаю, что у вас есть заказы, содержащие один и тот же SKU несколько раз (две отдельные позиции, обе заказывают один и тот же SKU).

8 голосов
/ 14 сентября 2015

У меня была такая же проблема, я использовал in вместо =, из примера базы данных Northwind:

Запрос: Найти компании, которые разместили заказы в 1997 году

Попробуйте это:

SELECT CompanyName
    FROM Customers
WHERE CustomerID IN (
                        SELECT CustomerID 
                            FROM Orders 
                        WHERE YEAR(OrderDate) = '1997'
                    );

Вместо этого:

SELECT CompanyName
    FROM Customers
WHERE CustomerID =
(
    SELECT CustomerID 
        FROM Orders 
    WHERE YEAR(OrderDate) = '1997'
);
6 голосов
/ 16 апреля 2010

Оператор выбора в части затрат вашего выбора возвращает более одного значения. Вам необходимо добавить дополнительные операторы where или использовать агрегацию.

4 голосов
/ 16 апреля 2010

Ошибка подразумевает, что этот подзапрос возвращает более 1 строки:

(Select Supplier_Item.Price from Supplier_Item,orderdetails,Supplier where Supplier_Item.SKU=OrderDetails.Sku and Supplier_Item.SupplierId=Supplier.SupplierID )

Скорее всего, вы не хотите включать в подзапрос таблицы orderdetails и supplier, поскольку хотите ссылаться на значения, выбранные из этих таблиц, во внешнем запросе. Поэтому я думаю, что вы хотите, чтобы подзапрос был просто:

(Select Supplier_Item.Price from Supplier_Item where Supplier_Item.SKU=OrderDetails.Sku and Supplier_Item.SupplierId=Supplier.SupplierID )

Предлагаю вам ознакомиться с коррелированными и некоррелированными подзапросами.

3 голосов
/ 16 апреля 2010

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

select  
  OrderDetails.Sku,
  OrderDetails.mf_item_number,
  OrderDetails.Qty,
  OrderDetails.Price,
  Supplier.SupplierId, 
  Supplier.SupplierName,
  Supplier.DropShipFees, 
  Supplier_Item.Price as cost
from 
  OrderDetails
join Supplier on OrderDetails.Mfr_ID = Supplier.SupplierId
join Group_Master on Group_Master.Sku = OrderDetails.Sku 
join Supplier_Item on 
  Supplier_Item.SKU=OrderDetails.Sku and Supplier_Item.SupplierId=Supplier.SupplierID 
where 
  invoiceid='339740' 
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...