SQL CASE ВЫБЕРИТЕ возвращаемый символ

#sql

#sql

Вопрос:

У меня есть 6 таблиц: LS_CLIENT_INSEE_A, B, C и т.д. Каждая таблица содержит только 1 поле: INSEE.

Я просто хочу знать, существует ли мой ввод в одной из этих таблиц, и возвращаю соответствующую букву из названия таблицы (A, B, C и т.д.).

Есть ли другая причина переписать это:

 @TheInsee int
AS
BEGIN
declare @Zone char(1)

declare @CountA int
declare @CountB int
declare @CountC int
declare @CountD int
declare @CountF int
declare @CountP int

SELECT @CountA = COUNT(*) FROM LS_CLIENT_INSEE_A WHERE NO_INSEE = @TheInsee
SELECT @CountB = COUNT(*) FROM LS_CLIENT_INSEE_B WHERE NO_INSEE = @TheInsee
SELECT @CountC = COUNT(*) FROM LS_CLIENT_INSEE_C WHERE NO_INSEE = @TheInsee
SELECT @CountD = COUNT(*) FROM LS_CLIENT_INSEE_D WHERE NO_INSEE = @TheInsee
SELECT @CountF = COUNT(*) FROM LS_CLIENT_INSEE_F WHERE NO_INSEE = @TheInsee
SELECT @CountP = COUNT(*) FROM LS_CLIENT_INSEE_P WHERE NO_INSEE = @TheInsee

set @Zone = 
      CASE 
         WHEN @CountA >  0   THEN 'A'
         WHEN @CountB >  0   THEN 'B'
         WHEN @CountC >  0   THEN 'C'   
         WHEN @CountD >  0   THEN 'D' 
         WHEN @CountF >  0   THEN 'F' 
         WHEN @CountP >  0   THEN 'P'         
      END  

END
  

Является ли приведенный выше запрос лучшим способом достижения этого?

Заранее благодарю вас, Стев

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

1. Я предлагаю вам подумать о нормализации этой базы данных!

Ответ №1:

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

Примечание: предполагается, что SQL Server (разница заключается в TOP 1 сравнении с LIMIT 1 ):

  @TheInsee int
AS
BEGIN
declare @Zone char(1)

SELECT @Zone = 
      CASE 
         WHEN (SELECT TOP 1 1 FROM LS_CLIENT_INSEE_A WHERE NO_INSEE = @TheInsee) >  0   THEN 'A'
         WHEN (SELECT TOP 1 1 FROM LS_CLIENT_INSEE_B WHERE NO_INSEE = @TheInsee) >  0   THEN 'B'
         WHEN (SELECT TOP 1 1 FROM LS_CLIENT_INSEE_C WHERE NO_INSEE = @TheInsee) >  0   THEN 'C' 
         WHEN (SELECT TOP 1 1 FROM LS_CLIENT_INSEE_D WHERE NO_INSEE = @TheInsee) >  0   THEN 'D'
         WHEN (SELECT TOP 1 1 FROM LS_CLIENT_INSEE_F WHERE NO_INSEE = @TheInsee) >  0   THEN 'F'
         WHEN (SELECT TOP 1 1 FROM LS_CLIENT_INSEE_P WHERE NO_INSEE = @TheInsee) >  0   THEN 'P'       
      END  
END
  

TOP 1 1 Это ярлык, предотвращающий сканирование всей таблицы, что важно, если NO_INSEE она не проиндексирована и таблица большая, она остановится при первом попадании и не продолжит сканирование всей таблицы.

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

1. Он прекратит обработку дополнительных таблиц после того, как найдет совпадение, но вам нужно будет использовать EXISTS , чтобы остановить обработку текущей таблицы после того, как она найдет совпадение.

2. Верно, не зная RDMS, я не могу решить, следует ли нам использовать SELECT TOP 1 1 или `ВЫБРАТЬ 1 .. ОГРАНИЧИТЬ 1″, есть ли общепринятый способ сделать это, не зная, какие RDMS?

Ответ №2:

Вы можете избавиться от всех @CountX переменных и выполнить следующее:

(SQL EXISTS() эффективно проверяет, завершается ли хотя бы одна строка и возвращается ли она немедленно, так что это будет быстрее, чем COUNT (*), потому что завершается при нахождении первой строки)

 SELECT @Zone = CASE WHEN EXISTS (
                           SELECT * FROM LS_CLIENT_INSEE_A 
                           WHERE NO_INSEE = @TheInsee 
                           )
                THEN 'A' END

...