Синтаксис выражения Case в предложении where создает проблему, заключающуюся в том, что подзапрос возвратил более 1 значения, когда подзапрос используется в качестве выражения. - PullRequest
1 голос
/ 28 июня 2019

Here is my table recored

Я хочу написать некоторый код, который возвращает все записи таблицы, если я выберу код отделения как пустой.

Но когда я выбираю код филиала, он должен возвращать запись только для определенного филиала.

   declare 
   @BRANCHCODE varchar(4)
   set @BRANCHCODE=''
   if (@BRANCHCODE='')
   begin
    SELECT  ID,BRANCHCODE,BRANCHNAME,DEPARTMENTCODE,DEPARTMENTNAME FROM RATINGLOGS
   WHERE BRANCHCODE in (SELECT  BRANCHCODE FROM RATINGLOGS)
   end 
   else
   begin
    SELECT  ID,BRANCHCODE,BRANCHNAME,DEPARTMENTCODE,DEPARTMENTNAME FROM RATINGLOGS
   WHERE BRANCHCODE=@BRANCHCODE
   end 

Над кодом вернитесь нормально.

Теперь я хочу использовать это условие в выражении case условия where. Код указан ниже:

    declare 
   @BRANCHCODE varchar(4)
   set @BRANCHCODE=''
   SELECT  ID,BRANCHCODE,BRANCHNAME,DEPARTMENTCODE,DEPARTMENTNAME FROM RATINGLOGS
   WHERE BRANCHCODE in (Case when @BRANCHCODE='' then (SELECT  BRANCHCODE FROM RATINGLOGS) else  @BRANCHCODE  end)

Возвращается нормально, когда я устанавливаю конкретный код филиала. Такие как

set @BRANCHCODE='1001'

Но его возвращение неверно:

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

Когда я использую

set @BRANCHCODE = ''

** Это упоминание, что я использую

BRANCHCODE in () 

, таких как поддержка более 1 значения. Я не использую (=,! =, <, <=,>,> =). Но это идет не так. **

Мне нужно объяснение вопроса и, если возможно, использование оператора case в предложении where, каким будет код перезаписи?

Ответы [ 4 ]

1 голос
/ 28 июня 2019

Оператор case может возвращать только 1 значение, поэтому при использовании ...then (select branchcode from ratinglogs) он возвращает все значения там, и это ошибка.

Если вы хотите объединить логику двух запросов в один, вы должны использовать логику "case", но не фактический оператор case:

WHERE (
(@BRANCHCODE='' and BRANCHCODE in (SELECT  BRANCHCODE FROM RATINGLOGS))
or
(not @BRANCHCODE='' and BRANCHCODE=@BRANCHCODE)
)
1 голос
/ 28 июня 2019

Условие in является избыточным в первом запросе - branchcode, запрашиваемый у ratinglogs, по определению должен находиться в списке всех branchcodes, выбранных из ratinglogs, поэтому вы можете просто удалить where предложение там полностью.

Имея это в виду, вы можете переписать запрос во втором фрагменте следующим образом:

SELECT id, branchcode, branchname, depatmentcode, departmentname
FROM   ratinglogs
WHERE  @branchcode IN (branchcode, '');
0 голосов
/ 28 июня 2019

вам не нужно никаких подзапросов

SELECT  ID,
        BRANCHCODE,
        BRANCHNAME,
        DEPARTMENTCODE,
        DEPARTMENTNAME 
FROM    RATINGLOGS
WHERE   (@BRANCHCODE = '' or BRANCHCODE = @BRANCHCODE)

Это вернет все строки, если переменная @BRANCHCODE = '', а иначе вернет только те строки, где BRANCHCODE = @ BRANCHCODE

Поскольку вы объявили @BRANCHCODE только как varchar (4), я предполагаю, что он всегда будет содержать только одно значение.
Если вам нужно, чтобы он содержал более одного кода, это не сработает

0 голосов
/ 28 июня 2019

Вам не нужен оператор IN(), ваш запрос может иметь вид

SELECT ID,
       BRANCHCODE,
       BRANCHNAME,
       DEPARTMENTCODE,
       DEPARTMENTNAME 
FROM RATINGLOGS
WHERE 1 = CASE WHEN @BRANCHCODE = '' THEN 1 ELSE 0 END --@BRANCHCODE = ''
      OR
      BRANCHCODE = @BRANCHCODE;

Приведенный выше код вернет все строки, если @BRANCHCODE = '', и если он содержит другое значение, онвернет конкретную строку, где BRANCHCODE = @BRANCHCODE.

Поскольку вы спрашиваете о выражении CASE, если вы хотите использовать оператор IN(), вы можете использовать другое решение с помощью @ Mureinik .

Если переменная @BRANCHCODE может содержать несколько значений, например: '1001,1002,1003', тогда она не будет работать так, как вы ожидаете, вам нужно будет разбить строку на строки.

SELECT ID,
       BRANCHCODE,
       BRANCHNAME,
       DEPARTMENTCODE,
       DEPARTMENTNAME 
FROM RATINGLOGS
WHERE BRANCHCODE = ''
      OR
      BRANCHCODE IN (SELECT Value FROM STRING_SPLIT(@BRANCHCODE, ','));

обратите внимание, что функция STRING_SPLIT() доступна только в версиях SQL Server 2016+, если у вас нет необходимости определять свой собственный

...