首页 > 解决方案 > 如何优化这些 SQL 连接?

问题描述

TL;博士

这是我要优化的连接查询。

SELECT D.Data1, D.Data2
FROM @DATA D
    INNER JOIN @FILTER F
        ON (
               (COALESCE(F.Filter1, D.Data1) = D.Data1)
               OR
               (
                   F.Filter1 < 0
                   AND F.Filter1 <> -D.Data1
               )
           )
           AND
           (
               (COALESCE(F.Filter2, D.Data2) = D.Data2)
               OR
               (
                   F.Filter2 < 0
                   AND F.Filter2 <> -D.Data2
               )
           );

背景

这是场景:

我有以下表格:

DECLARE @DATA TABLE (
    Data1 INT NOT NULL,
    Data2 INT NOT NULL,
--  ...
    DataN INT NOT NULL
);
DECLARE @FILTER TABLE (
    Filter1 INT NULL,
    Filter2 INT NULL,
--  ...
    FilterN INT NULL
)

需要根据以下规则按@DATA列过滤的行:@FILTER

令 1 < X < N。

假设FilterX IS NULL OR FilterX > 0所有 X 都为真。

假设DataX > 0所有 X 都为真。

  • 如果FilterX is NULL为真,则DataX通过过滤器。

  • 如果FilterX > 0 AND FilterX = DataX为真,则DataX通过过滤器。

  • 如果FilterX < 0 AND FilterX != -DataX为真,则DataX通过过滤器。

  • DataX否则过滤器失败。

  • 如果DataX全部通过过滤器,X则返回该DATA行。

这是一个两列方案:

COLUMNS:  Column1   Column2

DATA:     24        12
          23        12
          23        13 

FILTER:   24        NULL
          NULL      -12   

EXPECTED: 24        12
          23        13

上面的例子可以解释为

DATA返回where的所有行Data1 = 24 OR Data2 <> -12

我上面的查询完成了结果,但在商业案例中,我有大约 16 个字段而不是两个,这导致了一个丑陋可怕的查询。我想知道是否有一种更高效的方式可以进行这些连接以实现相同的结果。

标签: sqlsql-serverquery-performance

解决方案


您似乎遇到的主要问题是在WHERE子句中进行计算。你可以通过做这样的事情来避免其中的一些,我认为这符合你的逻辑。

    FROM @DATA D
    INNER JOIN @FILTER F
    ON 
    (
        (F.Filter1 = D.Data1 OR F.Filter1 IS NULL)
        OR
        (
            F.Filter1 < 0
            AND F.Filter1 <> -D.Data1
        )
    )
    AND
    (
        (F.Filter2 = D.Data2 OR F.Filter2 IS NULL)
        OR
        (
            F.Filter2 < 0
            AND F.Filter2 <> -D.Data2
        )
    );

在此之后我要查看的主要内容是您的表上是否有正确的索引,但我们无权访问您的实际架构来检查哪些索引已到位。


推荐阅读