AskOverflow.Dev

AskOverflow.Dev Logo AskOverflow.Dev Logo

AskOverflow.Dev Navigation

  • Início
  • system&network
  • Ubuntu
  • Unix
  • DBA
  • Computer
  • Coding
  • LangChain

Mobile menu

Close
  • Início
  • system&network
    • Recentes
    • Highest score
    • tags
  • Ubuntu
    • Recentes
    • Highest score
    • tags
  • Unix
    • Recentes
    • tags
  • DBA
    • Recentes
    • tags
  • Computer
    • Recentes
    • tags
  • Coding
    • Recentes
    • tags
Início / dba / Perguntas / 107876
Accepted
user2173353
user2173353
Asked: 2015-07-24 04:06:27 +0800 CST2015-07-24 04:06:27 +0800 CST 2015-07-24 04:06:27 +0800 CST

Melhor maneira de escrever uma consulta SQL que verifica uma coluna para um valor não NULL ou NULL

  • 772

Tenho um SP com um parâmetro que tem NULL como valor padrão e então quero fazer uma consulta assim:

SELECT ...
FROM ...
WHERE a.Blah = @Blah AND (a.VersionId = @VersionId OR (@VersionId IS NULL AND a.VersionId IS NULL));

O WHEREacima verifica um valor não NULL e um valor NULL para @VersionId.

Seria melhor em termos de desempenho usar uma IFinstrução e duplicar a consulta em uma que procura não NULL e outra para NULL assim? :

IF @VersionId IS NULL BEGIN
    SELECT ...
    FROM ...
    WHERE a.Blah = @Blah AND a.VersionId IS NULL;
ELSE BEGIN
    SELECT ...
    FROM ...
    WHERE a.Blah = @Blah AND a.VersionId = @VersionId;
END

Ou o otimizador de consulta torna essencialmente o mesmo?

ATUALIZAR:

(Nota: estou usando o SQL Server)

(E até onde eu sei, usar a.VersionId = @VersionIdpara ambos os casos não vai funcionar, vai?)

sql-server-2008 performance
  • 1 1 respostas
  • 10386 Views

1 respostas

  • Voted
  1. Best Answer
    Andriy M
    2015-07-24T06:43:53+08:002015-07-24T06:43:53+08:00

    Esse padrão

    column = @argument OR (@argument IS NULL AND column IS NULL)
    

    pode ser substituído por

    EXISTS (SELECT column INTERSECT SELECT @argument)
    

    Isso permitirá que você corresponda a um NULL com um NULL e permitirá que o mecanismo use um índice com columneficiência. Para uma excelente análise aprofundada dessa técnica, indico o artigo do blog de Paul White:

    • Planos de consulta não documentados: comparações de igualdade

    Como existem dois argumentos em seu caso particular, você pode usar a mesma técnica de correspondência com @Blah– dessa forma, você poderá reescrever toda a cláusula WHERE de forma mais ou menos concisa:

    WHERE
      EXISTS (SELECT a.Blah, a.VersionId INTERSECT SELECT @Blah, @VersionId)
    

    Isso funcionará rapidamente com um índice em (a.Blah, a.VersionId).


    Ou o otimizador de consulta torna essencialmente o mesmo?

    Neste caso, sim. Em todas as versões (pelo menos) do SQL Server 2005 em diante, o otimizador pode reconhecer o padrão e substituí-lo pela comparação col = @var OR (@var IS NULL AND col IS NULL)adequada . ISIsso depende da correspondência de reescrita interna, portanto, pode haver casos mais complexos em que isso nem sempre é confiável.

    Nas versões do SQL Server a partir de 2008 SP1 CU5 inclusive , você também tem a opção de usar a Otimização de Incorporação de Parâmetros via OPTION (RECOMPILE), onde o valor de tempo de execução de qualquer parâmetro ou variável é inserido na consulta como um literal antes da compilação.

    Assim, pelo menos em grande parte, neste caso a escolha é uma questão de estilo, embora a INTERSECTconstrução seja inegavelmente compacta e elegante.

    Os exemplos a seguir mostram o 'mesmo' plano de execução para cada variação (literais versus referências de variáveis ​​excluídas):

    DECLARE @T AS table
    (
        c1 integer NULL,
        c2 integer NULL,
        c3 integer NULL
    
        UNIQUE CLUSTERED (c1, c2)
    );
    
    -- Some data
    INSERT @T
        (c1, c2, c3)
    SELECT 1, 1, 1 UNION ALL
    SELECT 2, 2, 2 UNION ALL
    SELECT NULL, NULL, NULL UNION ALL
    SELECT 3, 3, 3;
    
    -- Filtering conditions
    DECLARE 
        @c1 integer,
        @c2 integer;
    
    SELECT
        @c1 = NULL,
        @c2 = NULL;
    
    -- Writing the NULL-handling out explicitly
    SELECT * 
    FROM @T AS T
    WHERE 
    (
        T.c1 = @c1
        OR (@c1 IS NULL AND T.c1 IS NULL)
    )
    AND 
    (
        T.c2 = @c2
        OR (@c2 IS NULL AND T.c2 IS NULL)
    );
    
    -- Using INTERSECT
    SELECT * 
    FROM @T AS T
    WHERE EXISTS 
    (
        SELECT T.c1, T.c2 
        INTERSECT 
        SELECT @c1, @c2
    );
    
    -- Using separate queries
    IF @c1 IS NULL AND @c2 IS NULL
        SELECT * 
        FROM @T AS T
        WHERE T.c1 IS NULL
        AND T.c2 IS NULL
    ELSE IF @c1 IS NULL
        SELECT * 
        FROM @T AS T
        WHERE T.c1 IS NULL
        AND T.c2 = @c2
    ELSE IF @c2 IS NULL
        SELECT * 
        FROM @T AS T
        WHERE T.c1 = @c1
        AND T.c2 IS NULL
    ELSE
        SELECT * 
        FROM @T AS T
        WHERE T.c1 = @c1
        AND T.c2 = @c2;
    
    -- Using OPTION (RECOMPILE)
    -- Requires 2008 SP1 CU5 or later
    SELECT * 
    FROM @T AS T
    WHERE 
    (
        T.c1 = @c1
        OR (@c1 IS NULL AND T.c1 IS NULL)
    )
    AND 
    (
        T.c2 = @c2
        OR (@c2 IS NULL AND T.c2 IS NULL)
    )
    OPTION (RECOMPILE);
    
    • 38

relate perguntas

  • Existe um processo do tipo "práticas recomendadas" para os desenvolvedores seguirem para alterações no banco de dados?

  • Como determinar se um Índice é necessário ou necessário

  • Downgrade do SQL Server 2008 para 2005

  • Onde posso encontrar o log lento do mysql?

  • Como posso otimizar um mysqldump de um banco de dados grande?

Sidebar

Stats

  • Perguntas 205573
  • respostas 270741
  • best respostas 135370
  • utilizador 68524
  • Highest score
  • respostas
  • Marko Smith

    conectar ao servidor PostgreSQL: FATAL: nenhuma entrada pg_hba.conf para o host

    • 12 respostas
  • Marko Smith

    Como fazer a saída do sqlplus aparecer em uma linha?

    • 3 respostas
  • Marko Smith

    Selecione qual tem data máxima ou data mais recente

    • 3 respostas
  • Marko Smith

    Como faço para listar todos os esquemas no PostgreSQL?

    • 4 respostas
  • Marko Smith

    Listar todas as colunas de uma tabela especificada

    • 5 respostas
  • Marko Smith

    Como usar o sqlplus para se conectar a um banco de dados Oracle localizado em outro host sem modificar meu próprio tnsnames.ora

    • 4 respostas
  • Marko Smith

    Como você mysqldump tabela (s) específica (s)?

    • 4 respostas
  • Marko Smith

    Listar os privilégios do banco de dados usando o psql

    • 10 respostas
  • Marko Smith

    Como inserir valores em uma tabela de uma consulta de seleção no PostgreSQL?

    • 4 respostas
  • Marko Smith

    Como faço para listar todos os bancos de dados e tabelas usando o psql?

    • 7 respostas
  • Martin Hope
    Jin conectar ao servidor PostgreSQL: FATAL: nenhuma entrada pg_hba.conf para o host 2014-12-02 02:54:58 +0800 CST
  • Martin Hope
    Stéphane Como faço para listar todos os esquemas no PostgreSQL? 2013-04-16 11:19:16 +0800 CST
  • Martin Hope
    Mike Walsh Por que o log de transações continua crescendo ou fica sem espaço? 2012-12-05 18:11:22 +0800 CST
  • Martin Hope
    Stephane Rolland Listar todas as colunas de uma tabela especificada 2012-08-14 04:44:44 +0800 CST
  • Martin Hope
    haxney O MySQL pode realizar consultas razoavelmente em bilhões de linhas? 2012-07-03 11:36:13 +0800 CST
  • Martin Hope
    qazwsx Como posso monitorar o andamento de uma importação de um arquivo .sql grande? 2012-05-03 08:54:41 +0800 CST
  • Martin Hope
    markdorison Como você mysqldump tabela (s) específica (s)? 2011-12-17 12:39:37 +0800 CST
  • Martin Hope
    Jonas Como posso cronometrar consultas SQL usando psql? 2011-06-04 02:22:54 +0800 CST
  • Martin Hope
    Jonas Como inserir valores em uma tabela de uma consulta de seleção no PostgreSQL? 2011-05-28 00:33:05 +0800 CST
  • Martin Hope
    Jonas Como faço para listar todos os bancos de dados e tabelas usando o psql? 2011-02-18 00:45:49 +0800 CST

Hot tag

sql-server mysql postgresql sql-server-2014 sql-server-2016 oracle sql-server-2008 database-design query-performance sql-server-2017

Explore

  • Início
  • Perguntas
    • Recentes
    • Highest score
  • tag
  • help

Footer

AskOverflow.Dev

About Us

  • About Us
  • Contact Us

Legal Stuff

  • Privacy Policy

Language

  • Pt
  • Server
  • Unix

© 2023 AskOverflow.DEV All Rights Reserve