#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
...