在oracle中找到最近的不同类型的行

时间:2015-12-07 19:04:57

标签: oracle exists

我的表格似乎是

__   Key   type  timeStamp             flag
1 )    1     B    2015-06-28 22:19:26   Y
2 )    1     B    2015-06-28 22:20:22   Y
3 )    1     C    2015-06-28 22:22:06   N
4 )    1     A    2015-06-28 22:25:11   N
5 )    1     B    2015-06-28 22:29:44   Y
6 )    1     A    2015-06-28 22:33:33   N
7 )    1     B    2015-06-28 22:35:21   N
8 )    1     B    2015-06-28 22:39:34   Y
9 )    1     B    2015-06-28 22:43:53   N
10)    1     A    2015-06-28 22:45:53   N

我需要找出所有类型的A flag='N',其中存在类型B的timestampOF(B)<timestampOF(A)Flag(B)='Y'以及key(A)=key(B)

注意:如果B之前存在两个B而不是B带有最大时间戳。(ROW [8,9,10] 9代替8)

输出

__   Key   type  timeStamp             flag
4 )    1     A    2015-06-28 22:25:11   N
6 )    1     A    2015-06-28 22:33:33   N

我的方法

SELECT  *
FROM    tab TAB_OUT
WHERE   TAB_OUT.TYPE='A'
    AND TAB_OUT.FLAG='N'
    AND EXISTS(
            SELECT   *
            FROM    tab TAB_IN
            WHERE   TAB_IN.KEY = TAB_OUT.KEY
                    AND     TAB_IN.TYPE='B'
                    AND     TAB_OUT.FLAG='Y'
                    AND     TAB_IN.timestamp<TAB_OUT.timestamp
                    AND     TAB_IN.timestamp = (SELECT MAX(timestamp) from       
 tab where timestamp< `TAB_OUT.timestamp`)
 );
  1. 但在此我无法在第三级查询中使用TAB_OUT.timestamp。有没有其他解决方案来解决这个问题。

  2. 在我的查询中note:部分不满足我的查询,因为它不会跳过。 9)并满足条件,没有。 8)

2 个答案:

答案 0 :(得分:1)

SELECT
    *
FROM
    tab A
WHERE
    flag = 'N' AND type = 'A'
    AND EXISTS (
        SELECT
            NULL
        FROM
            tab B
        WHERE
            type = 'B'
            AND A.timestamp > timestamp AND A.Key = Key
        GROUP BY
            Key
        HAVING
            MAX(flag) KEEP (DENSE_RANK LAST ORDER BY timestamp) = 'Y'
    );

无需进行相关查询以从最后一条记录中选择标记。使用聚合KEEP子句是更有效的方法。在这种情况下,它按时间戳对组进行排序,并仅保留聚合的最后一个值(您想要的最后一个时间戳),因此MAX函数只有一条记录,我们只从中获取FLAG值。

这是一个简单的例子:

WITH sample (value1, value2) AS (
    SELECT 1, 'Y' FROM DUAL UNION ALL
    SELECT 2, 'X' FROM DUAL
)
SELECT
    MIN(value2) KEEP (DENSE_RANK LAST ORDER BY value1) value2
FROM
    sample

这将从具有最高值1的记录中返回value2。

答案 1 :(得分:1)

只需要一次表扫描的解决方案:

SQL Fiddle

Oracle 11g R2架构设置

CREATE TABLE table_name ( Key, type, timeStamp, flag ) AS
          SELECT 1, 'B', CAST( TIMESTAMP '2015-06-28 22:19:26' AS DATE ), 'Y' FROM DUAL
UNION ALL SELECT 1, 'B', CAST( TIMESTAMP '2015-06-28 22:20:22' AS DATE ), 'Y' FROM DUAL
UNION ALL SELECT 1, 'C', CAST( TIMESTAMP '2015-06-28 22:22:06' AS DATE ), 'N' FROM DUAL
UNION ALL SELECT 1, 'A', CAST( TIMESTAMP '2015-06-28 22:25:11' AS DATE ), 'N' FROM DUAL
UNION ALL SELECT 1, 'B', CAST( TIMESTAMP '2015-06-28 22:29:44' AS DATE ), 'Y' FROM DUAL
UNION ALL SELECT 1, 'A', CAST( TIMESTAMP '2015-06-28 22:33:33' AS DATE ), 'N' FROM DUAL
UNION ALL SELECT 1, 'B', CAST( TIMESTAMP '2015-06-28 22:35:21' AS DATE ), 'N' FROM DUAL
UNION ALL SELECT 1, 'B', CAST( TIMESTAMP '2015-06-28 22:39:34' AS DATE ), 'Y' FROM DUAL
UNION ALL SELECT 1, 'B', CAST( TIMESTAMP '2015-06-28 22:43:53' AS DATE ), 'N' FROM DUAL
UNION ALL SELECT 1, 'A', CAST( TIMESTAMP '2015-06-28 22:45:53' AS DATE ), 'N' FROM DUAL

查询1

SELECT  Key,
        type,
        timeStamp,
        flag
FROM (
  SELECT  Key,
          type,
          timeStamp,
          flag,
          LAG( CASE WHEN type = 'B' THEN flag END ) IGNORE NULLS OVER ( PARTITION BY Key ORDER BY timeStamp ) AS prev_b_flag
  FROM    table_name t
  WHERE   type IN ( 'A', 'B' )
)
WHERE   type        = 'A'
AND     flag        = 'N'
AND     prev_b_flag = 'Y'

<强> Results

| KEY | TYPE |              TIMESTAMP | FLAG |
|-----|------|------------------------|------|
|   1 |    A | June, 28 2015 22:25:11 |    N |
|   1 |    A | June, 28 2015 22:33:33 |    N |