SQL - наиболее эффективный способ условно исключить объединение?(если это вообще возможно) - PullRequest
1 голос
/ 30 октября 2010

Если у меня есть следующая структура таблицы ...

Table 1: BlogPost

PostId |  Name | Text    

Table 2: Tags

TagId  | Tag    

Table 3: BlogPostTag

PostId | TagId

И следующая хранимая процедура ...

CREATE PROCEDURE SearchBlogPosts

    @tagstring nvarchar(max),

AS
BEGIN

    DECLARE @searchTags TABLE (Tag varchar(50));

    IF @tagstring IS NOT NULL AND @tagstring <> ''
        BEGIN
            INSERT INTO @tags SELECT s AS tag FROM dbo.Split(',',@tagstring);
        END

    SELECT * FROM BlogPost b
        JOIN BlogPostTags bt on bt.PostId = b.PostId    
        JOIN Tags t on t.TagId = bt.TagId
        JOIN @searchTags st ON st.Tag = t.Tag
            ...
        (Other Joins and where clauses may exist below here)
END

... какой самый "производительный" способв котором я мог бы исключить объединения в таблицах тегов, если @tagstring является нулевым или пустым?

Ответы [ 3 ]

2 голосов
/ 30 октября 2010

Единственный способ (а также лучший способ) указать условные объединения - это иметь разные запросы:

IF @tagstring IS NOT NULL AND @tagstring <> '' 
BEGIN
    SELECT * FROM BlogPost b 
        JOIN BlogPostTags bt on bt.PostId = b.PostId     
        JOIN Tags t on t.TagId = bt.TagId 
        JOIN @searchTags st ON st.Tag = t.Tag 
END
ELSE
BEGIN
    SELECT * FROM BlogPost b 
        JOIN BlogPostTags bt on bt.PostId = b.PostId     
        JOIN Tags t on t.TagId = bt.TagId 
END

SQL является декларативным языком доступа к данным языком, а не языком обязательной обработки вашего приложения. Любой объявленный вами запрос должен создать путь доступа, который работает во всех случаях . Наличие условной логики в запросе - наихудшая вещь, которую вы можете сделать, она заставляет планы доступа, которые обычно сканируют все возможные данные, потому что они не могут определить, являются ли условия истинными или ложными в плане создание время .

0 голосов
/ 30 октября 2010

Я думаю, что лучшая производительность, которую вы можете получить, это не запускать запрос, если @tagstring имеет значение null или пусто. Если во всех внутренних объединениях и @searchTags отсутствуют строки, строки никогда не будут возвращены.

Таким образом, вы можете переместить оператор SELECT в оператор IF, когда блок true.

0 голосов
/ 30 октября 2010

Я не думаю, что указание левого соединения повлечет за собой снижение производительности (я предполагаю, что @searchTags пуст, если @tagstring равно нулю или пусто).

Или вы не хотите понизить производительность за присоединение @searchTags к тегам?

В вашем примере не совсем понятно, откуда берутся данные в @searchtags.

LEFT JOIN Tags t on t.TagId = bt.TagId AND @tagstring is not null AND @tagstring <> ''

Сервер должен быть достаточно умным, чтобы вообще не пытаться подключиться с этим условием. Я бы не подумал, что это может привести к значительному снижению производительности в любом случае.

Если вы хотите, чтобы столбцы вообще не отображались в результате, по какой-то причине блок IF ... ELSE с двумя различными запросами - это самый простой способ сделать это.

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