左外连接使用left()函数

时间:2018-06-08 14:33:18

标签: sql sql-server left-join

我每天(过夜)运行以下查询,并且需要相当长的时间才能运行(1-1.5小时)。我确定" Acc.DateKey> = LEFT(LocationKey,8)"是原因,如果连接的这部分被删除,查询将在大约5分钟内执行。我想不出更有效的方式。

Acc.DateKey通常是20180101等,其中位置键通常为201801011234等。

到目前为止,我已经考虑在LO表格中添加一个新列" AccLocationKey"在加载时将使用LEFT(LocationKey,8)函数插入。

我已经决定先在这里提出问题 - 如果不改变LO表,可以改进吗?

SELECT
ISNULL(MAX(L.LocationKey),(SELECT MIN(LocationKey) FROM LO WHERE Location = Acc.Location)) AS LocationKey
FROM
Acc
LEFT OUTER JOIN
(
    SELECT
        LocationKey
        ,Location
    FROM
        LO
)AS L
ON Acc.Location = L.Location AND Acc.DateKey >= LEFT(LocationKey,8)

1 个答案:

答案 0 :(得分:0)

让我们在SELECT

中没有子查询的情况下重写查询
SELECT COALESCE(MAX(L.LocationKey), MIN(L.MIN_LocationKey)) AS LocationKey
FROM Acc LEFT OUTER JOIN
     (SELECT MIN(l.LocationKey) OVER (PARTITION BY l.Location) as min_location,
             l.*
      FROM LO l
     ) L
     ON Acc.Location = L.Location AND Acc.DateKey >= LEFT(l.LocationKey, 8);

可能性能最佳的机会是添加计算列和适当的索引。所以:

alter table lo add locationkey_datekey as (try_convert(bigint, LEFT(l.LocationKey, 8))) persisted;

然后,适当的索引:

create index idx_lo_location_datekey on lo(location, locationkey_datekey);

然后在查询中使用它:

SELECT COALESCE(MAX(L.LocationKey), MIN(L.MIN_LocationKey)) AS LocationKey
FROM Acc LEFT OUTER JOIN
     (SELECT MIN(l.LocationKey) OVER (PARTITION BY l.Location) as min_location,
             l.*
      FROM LO l
     ) L
     ON Acc.Location = L.Location AND Acc.DateKey >= l.LocationKey_datekey;

令人高兴的是,这个索引也适用于窗口函数。