【问题标题】:Look-up another row based on current row in in the same table in Oracle在Oracle的同一张表中根据当前行查找另一行
【发布时间】:2012-06-03 20:46:07
【问题描述】:

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

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

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

  1. 事件ID
  2. 标签名称
  3. 标签值
  4. PreviousConditionTag
  5. PreviousConditionValue

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)

有什么想法吗?

【问题讨论】:

    标签: sql oracle plsql oracle9i


    【解决方案1】:

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

    您希望查找重叠的标签集,但仍要获取上一个事件 ID。思路如下:

    1. 将所有当前标签的标识添加到映射表中(因此当前标签 = 条件标签)
    2. 根据条件标签加入映射表,获取当前匹配的标签。因此,这些行将使用它们匹配的“当前”标签重新标记,您可以将其用于延迟。
    3. 根据滞后逻辑获取最新的 EventId,按 Current 标签进行分区。
    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
      

    这可能看起来违反直觉,因为您是根据情况而不是当前情况向后查找事物。而且,您正在乘以正在处理的行数。但是,它可能仍然比您使用的连接解决方​​案更快。

    【讨论】:

    • 这种情况下偏移量的目的是什么? Oracle LAG() 分析有一个我可以指定的偏移量,在我只需要给定标签的前一个值的简单情况下,偏移量是 1。在这种情况下,从技术上讲,偏移量仍然是“1”,但分区不那么直截了当。在原始数据中,我正在寻找的前一个标签可能已经出现在任意数量的行之前(当按事件 id 排序时,它并不总是出现在当前行之前)。
    • 我很抱歉。我最好理解这个问题,然后重新回答。我可能把 ConditionTagName 和 CurrentTagName 倒过来了。
    • 没问题,感谢您再次查看!您建议按条件而不是当前值向后查找似乎有很大的不同。我重写了我的查询来执行此操作,现在它在不到一秒的时间内完成,而不是之前的 5 或 6 秒。感谢您的帮助!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-10-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多