Попытка использовать подзапрос в качестве выражения, нужна альтернатива / помощь - PullRequest
0 голосов
/ 05 июля 2011

SQL Server 2005.

У меня есть хранимая процедура, которая принимает несколько параметров, которые могут или не могут иметь данные, переданные им.Таким образом, они могут отображаться в виде пустой строки или с данными.

Данные будут представлять собой список идентификаторов с разделителями ... идентификатор производителя, идентификатор каталога и т. Д. Процесс выполняет поиск записей,и если какой-либо из этих параметров имеет данные, он используется в предложении where.

FYI: Split - это функция, которая разбивает строку (принимает разделитель) и возвращает таблицу.


WHERE

...

AND m.Mfg_ID in (CASE WHEN @manufacturerIds <> '' THEN (SELECT * FROM Split(@manufacturerIds, '|')) ELSE (select m.Mfg_Id) END)

Я получаю сообщение об ошибке: «Подзапрос возвратил более 1 значения. Это недопустимо, если подзапрос следует =,! =, <, <=,>,> = Или когда подзапрос используется в качестве выражения."

Чего я не понимаю, так это того, что если я удаляю оператор CASE, чтобы у меня было только это ...


WHERE

...

AND m.Mfg_ID in (SELECT * FROM Split(@manufacturerIds, '|'))

... он работает нормально;однако, это лишает меня возможности передавать пустую строку.

Любая помощь будет принята с благодарностью!

Ответы [ 4 ]

2 голосов
/ 05 июля 2011

Разница в том, что (select m.Mfg_Id) возвращает одну строку, а (select * from split(...)) возвращает несколько строк.case возвращает одно значение, поэтому он не знает, что делать с несколькими строками из Split.

Вместо case вы можете объединить их вместе:

and m.Mfg_ID in 
(
select  *
from    Split(@manufacturerIds, '|')
where   @manufacturerIds <> ''
union all
select  m.Mfg_Id
where   @manufacturerIds = ''
)

Нижняя половина union работает только тогда, когда @manufacturerIds = ''.

1 голос
/ 05 июля 2011
SELECT m.Mfg_ID -- , other columns
    FROM dbo.base_table_name AS m
    LEFT OUTER JOIN dbo.Split(@ManufacturerIds) AS f
    ON (m.Mfg_id = f.column_name)
    WHERE @manufacturerIds = '' 
    OR f.column_name IS NOT NULL;
0 голосов
/ 05 июля 2011

Я пытался переписать ваше предложение "где" на что-то, что мне кажется более логичным. Вместо того, чтобы разбивать текст на более мелкие биты, я сравниваю текст с «LIKE». Я предполагаю, что это даст лучшую производительность.

DECLARE @t table (Mfg_id VARCHAR(10))
DECLARE @manufacturerIds VARCHAR(50)
INSERT @t 
SELECT 'aaa' UNION ALL SELECT 'a' UNION ALL SELECT 'ab' UNION ALL SELECT 'abc'

SET @manufacturerIds = '|' +'aaa|abc|bbb' + '|'

SELECT Mfg_ID matching FROM @t m
WHERE ( @manufacturerIds like '%|' + CAST(m.Mfg_ID AS VARCHAR(20)) + '|%' OR @manufacturerIds = '')

Результат:

matching
----------
aaa
abc

Если вы хотите, чтобы ваш корректный сценарий был исправлен, вот как вы можете это сделать:

AND (@manufacturerIds = '' or m.Mfg_ID in (SELECT * FROM Split(@manufacturerIds, '|')))
0 голосов
/ 05 июля 2011

Я думаю, что это может быть связано с частью 'SELECT *' подзапроса CASE.Попробуйте выбрать только один столбец.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...