1

假设我有一个包含三列的表:

  1. 事件ID (PK)
  2. 标签名称
  3. 标签值

我需要创建一个查询,结果如下:

  1. 事件ID
  2. 标签名称
  3. 标签值
  4. 上一个条件标签
  5. 上一个条件值

其中 PreviousConditionTag/Value 来自上一行的 TagName 和 TagValue(按 EventID 排序时)。

在这个问题的一个更简单的版本中,PreviousConditionTag 始终与 TagName 相同——也就是说,我只需要检索当前 TagName 的先前值。我使用 Oracle 的 LAG 分析函数解决了这个问题,按 TagName 进行分区。

但是,我现在需要执行类似的操作,但对于 PreviousConditionTag 是通过另一个表与 TagName 相关的任意标记的情况,其中 TagName 和 PreviousConditionTag 之间的关系不是一对一的。

例如,如果给定行的 TagName 为“ABC”,则关系表可能会说我需要查找“IJK”或“XYZ”的先前值。

我能够在一个 Oracle 函数中提出这个逻辑,该函数对同一个表执行 SELECT 并查找与条件匹配的 MAX(EventID)。例如:

SELECT * FROM MyTable WHERE EventID = (
    SELECT MAX(EventID) FROM MyTable WHERE TagName IN (
        SELECT ConditionTagName FROM ConditionMappingTable WHERE TagName = [CurrentTagName]
    )
) AND EventID <= [CurrentEventId]

但是,正如您可以想象的那样,由于此查询是在 MyTable 的每一行的函数中执行的,因此我担心它的性能。

我试图想办法再次使用 Oracle 的 LAG 分析,但我不确定如何为它提出 PARTITION 子句,因为分区似乎重叠。(例如标签ABC需要看IJK和XYZ,标签DEF需要看IJK和UVW)

有任何想法吗?

4

1 回答 1

1

这是答案的重写形式,现在我更好地理解了它。

您想要查找重叠的标签集并仍然获得先前的事件 ID。思路如下:

  1. 将所有当前标签的标识添加到映射表(因此当前标签 = 条件标签)
  2. 根据条件标签加入映射表,获取当前匹配的标签。因此,行将使用它们匹配的“当前”标签重新标记,您可以将其用于滞后。
  3. 根据滞后逻辑获取最新的 EventId,按当前标签进行分区。
  4. 选择当前和条件标签相同的结果。

    select t.*
    from (select t.*, mt.CurrentTagName, mt.ConditionTagName,
             lag(EventId, 1, NULL)
             over (partition by mt.CurrentTagName
                   order by EventId)
      from t join
           (select CurrentTagName, ConditionTagName
            from ((select CurrentTagName, ConditionTagName
                   from ConditionMappingTable mt
                  ) union all
                  (select distinct CurrentTagName, CurrentTagName
                   from ConditionMappingTable mt
                  )
                 ) mt
           )
           on mt.ConditionTagName = t.tagname
     ) t
    on CurrentTagName = ConditionTagName
    

这似乎有悖常理,因为您是根据情况而不是当前情况来向后查找的。而且,您正在乘以正在处理的行数。但是,它可能仍然比您使用的连接解决方​​案更快。

于 2012-05-29T15:56:59.317 回答