将“ LIST”表与“ SPAN”表联接

时间:2019-08-26 15:05:30

标签: sql firebird firebird-3.0

在Firebird中,我有一个表是“列表”。它包含如下记录:

LstRecID
1
2
3
4
5
6
7
8
9
10
...

我还有另一个包含各种“跨度”的表。它包含如下记录:

  SpnRecID | BeginSpan | EndSpan 
 ----------|-----------|--------- 
  A        |         1 |       3 
  B        |         4 |       6 
  C        |         7 |       8 

我需要一个 ALL LstRecID(最左侧一列)的列表。在接下来的几列中,我希望在范围开始或结束之间匹配或落入范围的任何范围记录的SpnRecID,或者,如果没有具有匹配范围或包围范围的范围记录,则为空白。像这样:

  LstRecID | SpnRecID 
 ----------|---------- 
         1 | A        
         2 | A        
         3 | A        
         4 | B        
         5 | B        
         6 | B        
         7 | C        
         8 | C        
         9 |          
        10 |          

实际上,我的列表表包含150万条记录。我以为我可以做一个BETWEEN,但是事实证明这太慢了。我在两个表的所有字段上都有索引。

我需要不超过750毫秒的结果。

SELECT List.LstRecID, Span.SpnRecID
FROM List LEFT JOIN
     Span
     on List.LstRecID BETWEEN Span.BeginSpan and Span.EndSpan

以上操作大约需要15分钟。

SELECT List.LstRecID, Span.SpnRecID
FROM List LEFT JOIN
     Span
     on List.LstRecID = ANY (SELECT List.LstRecID 
                             where List.LstRecID BETWEEN Span.BeginSpan and Span.EndSpan)

以上操作大约需要15分钟。

必须有一种更好的方法来显示包含跨度的列表,该跨度将比此操作更快。你有什么建议吗?这是我的问题。

3 个答案:

答案 0 :(得分:0)

此查询是否有更好的性能?

SELECT l.LstRecID,
       (SELECT MAX(s.BeginSpan)
        FROM Span s
        WHERE l.LstRecID >= s.BeginSpan
       ) as SpnRecID
FROM List l ;

您要在Span(BeginSpan desc)上建立索引。这可能更容易优化。

我没有完全得到你想要的。但是,如果性能令人满意,那么您真正想要的只是join

鉴于您的数据量,如果能在不到几秒钟的时间内获得结果,我会感到惊讶。

编辑:

在示例数据中,所有范围的开头都有一个匹配项。如果可以保证,请尝试:

SELECT l.LstRecID,
       COALESCE(s.BeginSpan,
                MAX(s.BeginSpan) OVER (ORDER BY l.LstRecID)
               ) as BeginSpan
FROM List l LEFT JOIN
     Span s
     ON l.LstRecID = s.BeginSpan;

答案 1 :(得分:0)

我能够得到我想要的结果集,即每一行包括的所有字段,以及没有跨度的空白,结果返回75毫秒(允许的最大时间的十分之一,限制跨度表子选择中跨度表的大小(返回的行)。

SELECT
  ...list and span fields you want to see...
FROM
  (SELECT ..list fields that match above.. FROM list table WHERE LstRecID BETWEEN your low limit AND your high limit) AS your list alias
  LEFT JOIN
    (SELECT
      ... your span fields that match above ...
      FROM span table s
      WHERE
        (s.span low limit >= your same low limit) AND 
        (s.span high limit <= your same high limit) AS s
    ON (LstRecID BETWEEN s.BeginSpan AND s.EndSpan)
ORDER BY List.LstRecID

答案 2 :(得分:0)

  1. 将列span_id添加到lists表中,将其foreign key添加到spans表中,并添加check constraint就足以满足{ {1}}条件。

  2. between表上添加after update or insert or delete触发器,并在spans中受lists的每次更改影响的行中更新spans中的行

  3. 以“ 15分钟”的请求一次对新添加的列进行初始填充