使用嵌套子查询在Oracle中使用rownum选择记录,从而导致无效的标识符错误

时间:2015-06-21 22:23:23

标签: sql oracle join subquery case

以下查询给出了无效的标识符错误(a.id),因为它在嵌套的子查询中:

SELECT a.*, 
CASE WHEN
SELECT id FROM (SELECT id, ROWNUM rnum FROM US b WHERE b.id = a.id ORDER BY b.createdate ASC) WHERE rnum = 2) = 21 THEN ‘Found’
END SEARCH
FROM EU a 
JOIN US b ON b.id = a.id;

有人可以建议我替代方法吗?

2 个答案:

答案 0 :(得分:1)

您还没有详细描述您的设置或您想要实现的目标,但这会解决它吗?

SQL Fiddle

Oracle 11g R2架构设置

CREATE TABLE EU ( id ) AS
SELECT 19+LEVEL
FROM   DUAL CONNECT BY LEVEL <= 5;

CREATE TABLE US ( id, createdate ) AS
SELECT 19+LEVEL, SYSDATE - LEVEL
FROM   DUAL CONNECT BY LEVEL <= 5
UNION ALL
SELECT 19+2*LEVEL, SYSDATE-LEVEL-5
FROM   DUAL CONNECT BY LEVEL <= 3;

查询1

SELECT a.*,
       CASE WHEN a.id = 21
             AND ROW_NUMBER() OVER ( PARTITION BY a.id ORDER BY b.createdate ) = 2
            THEN 'Found'
             END AS SEARCH
FROM   EU a 
JOIN   US b
ON     b.id = a.id

<强> Results

| ID | SEARCH |
|----|--------|
| 20 | (null) |
| 21 | (null) |
| 21 |  Found |
| 22 | (null) |
| 23 | (null) |
| 23 | (null) |
| 24 | (null) |

答案 1 :(得分:0)

您的查询存在的一个问题是第二个SELECT之前缺少paren。我仍然认为它不会起作用,因为Oracle将标识符的范围限制在一层深层。但这就是我认为你想要的:

SELECT a.*, 
       (CASE WHEN (SELECT id
                   FROM (SELECT id, ROWNUM as rnum
                         FROM US b
                         WHERE b.id = a.id
                         ORDER BY b.createdate ASC
                        )
                   WHERE rnum = 2
                  ) = 21 THEN ‘Found’
        END) SEARCH
FROM EU a JOIN
     US b
     ON b.id = a.id;

获得所需内容的最简单方法是使用row_number()

select a.*,
       (case when b.id = 21 then 'Found' end) as Search
from eu a left join
     (select b.*,
             row_number() over (partition by b.id order by b.createddate) as seqnum
      from us b
     ) b
     on b.id = a.id
where seqnum = 2;

查询看起来很奇怪,因为id用于所有内容。你似乎在寻找id 21的两条记录。