SQL если (существует ()) дублирование запроса - PullRequest
3 голосов
/ 14 мая 2009

Мне нужно написать запрос, который получает набор информации из таблицы, но если нет информации для этого конкретного клиента, используйте набор по умолчанию. Мне было интересно, есть ли способ избежать дублирования запросов в операторе if (exist ()).

Например:

IF( EXISTS( SELECT * FROM UserTable WHERE Name = @UserName))
BEGIN
    SELECT * FROM UserTable WHERE Name = @UserName))
END
ELSE
BEGIN
    SELECT * FROM UserTable WHERE Name = 'Jon Skeet'))
END

Первые два выбора (существует и истинная часть if) абсолютно одинаковы. Я хочу избежать запуска одного и того же запроса дважды, если утверждение верно. Я знаю, что существуют остановки, когда первое истинное условие выполнено, но это все еще O (n) худший случай.

Другая известная мне опция - поместить информацию в временную таблицу и проверить, есть ли информация, если нет, вернуть информацию по умолчанию.

Оба способа будут работать, но как лучше всего это сделать? Есть ли другие способы сделать это? Есть ли способ сделать это в предложении WHERE, поскольку это единственное, что отличается?

Редактировать: Исправлен пример возврата строки, а не только одного элемента. Таким образом, ответы на сброс выборки в одну переменную будут равны временной таблице, которую я предполагаю. Также, чтобы не разозлить Джона Скита, пишется его имя правильно

Ответы [ 6 ]

6 голосов
/ 14 мая 2009

Вы можете сделать это:

SELECT TOP 1
     UserID
FROM
     UserTable
WHERE
     Name IN (@UserName, 'John Skeet')
ORDER BY
     CASE WHEN Name = 'John Skeet' THEN 2 ELSE 1 END

(или используйте LIMIT или любой другой метод для вашей РСУБД)

Или вы могли бы сделать это:

DECLARE @UserID INT

SELECT
     @UserID = UserID
FROM
     UserTable
WHERE
     Name = @UserName

IF (@UserID IS NULL)
     SELECT
          @UserID = UserID
     FROM
          UserTable
     WHERE
          Name = 'John Skeet'

SELECT @UserID AS UserID

Или это:

SELECT
     COALESCE(T2.UserID, T1.UserID)
FROM
     UserTable T1
LEFT OUTER JOIN UserTable T2 ON
     T2.Name = @UserName
WHERE
     T1.Name = 'John Skeet'

Или это:

SELECT
     UserID
FROM
     UserTable
WHERE
     Name = @UserName

IF (@@ROWCOUNT = 0)  -- MS SQL Server specific, your RDBMS method will vary
     SELECT
          UserID
     FROM
          UserTable
     WHERE
          Name = 'John Skeet'
3 голосов
/ 14 мая 2009

Как насчет:

DECLARE @UserID int;
SELECT @UserID = UserID FROM UserTable WHERE Name = @UserName

IF(@UserID IS NULL)
BEGIN
    SELECT @UserID=UserID FROM UserTable WHERE Name = 'Jon Skeet'))
END

SELECT @UserID
1 голос
/ 14 мая 2009

Если вы беспокоитесь о производительности, я думаю, что вам, вероятно, не нужно - большинство СУБД должны оптимизировать дублирование. Если вы все еще беспокоитесь о производительности, запустите ее в обоих направлениях, чтобы увидеть, есть ли у вашей СУБД какие-либо проблемы с ней.

Если вас беспокоит код - возможность сопровождения дублированных разделов кода, удобочитаемость и т. П., Изучите приведенные выше ответы с учетом этого. Вы можете обнаружить, что дублирование - ваш наименее худший вариант. Обидно, что SQL не более податлив.

1 голос
/ 14 мая 2009

Вы можете выбрать переменную, проверить переменную, если она вернется, null, выполнить запрос get default

как то так:

Declare @uID int;

SELECT @uID = UserID FROM UserTable WHERE Name = @UserName

IF (@uID is null)
begin 
'Select default here'
End

select @uID
0 голосов
/ 14 мая 2009

Если вы не собираетесь определять набор переменных для каждого возвращаемого поля (и это только одна запись), я думаю, что наиболее эффективный способ - сделать вызов дважды. Временная таблица, вероятно, будет стоить дороже.

0 голосов
/ 14 мая 2009

Вы не говорите, какую СУБД вы используете, но это явно не Oracle (это та, которую я знаю). Однако я ожидаю, что ваша СУБД позволит вам сделать что-то вроде этого псевдокода:

SELECT UserID FROM UserTable WHERE Name = @UserName
IF <no data returned by that> 
BEGIN
    SELECT UserID FROM UserTable WHERE Name = 'John Skeet'
END

В Oracle это будет:

BEGIN
    SELECT UserID INTO v_UserID FROM UserTable WHERE Name = :UserName;
EXCEPTION
    WHEN NO_DATA_FOUND THEN
    SELECT UserID INTO v_UserID FROM UserTable WHERE Name = 'John Skeet';
END
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...