2012-03-30 64 views
0

我有2列在一对多的关系。我想对“许多”进行排序并返回“one”的第一个出现。我需要翻阅数据,例如,我需要能够获得第三组10个唯一的“一个”值。在Oracle中,如何从排序结果中获取不同值的页面?

我有这样的查询:

SELECT id, name 
FROM table1 
INNER JOIN table2 ON table2.fkid = table1.id 
ORDER BY name, id; 

可以有表2为表1中的每一行多行。

我的查询看起来像这样的结果:

id | name 
---------------- 
    2 | apple 
    23 | banana 
    77 | cranberry 
    23 | dark chocolate 
    8 | egg 
    2 | yak 
    19 | zebra 

我需要翻阅结果与包含n 独特 IDS每个页面设置。例如,如果启动= 1和N = 4我想回去

2 
23 
77 
8 

在自己被划分成上(即名称),其中ID是在其第一次出现的位置返回的顺序。同样,如果开始= 3和n = 4,为了=降序我想

8 
23 
77 
2 

我尝试这样做:

SELECT * FROM (
    SELECT id, ROWNUM rnum FROM (
    SELECT DISTINCT id FROM (
     SELECT id, name 
     FROM table1 
     INNER JOIN table2 ON table2.fkid = table1.id 
     ORDER BY name, id) 
    WHERE ROWNUM <= 4) 
    WHERE rnum >=1) 

这给了我的ID数字顺序,而不是有序的名称将是。

我也试过:

SELECT * FROM (
    SELECT DISTINCT id, ROWNUM rnum FROM (
    SELECT id FROM (
     SELECT id, name 
     FROM table1 
     INNER JOIN table2 ON table2.fkid = table1.id 
     ORDER BY name, id) 
    WHERE ROWNUM <= 4) 
    WHERE rnum >=1) 

但是这给了我重复值。

如何翻阅此数据的结果?我只需要这个ID,没有什么来自“多”表。

更新

我想我得到与改变我的内部查询接近

SELECT id, name, rank() over (order by name, id) 
FROM table1 
INNER JOIN table2 ON table2.fkid = table1.id 

...但我仍然得到重复的ID。

+1

如果您需要为结果分页,您的应用程序的搜索功能可能会中断。阅读Jeff Atwood最近的这篇博客(这个教区的晚期):http://www.codinghorror.com/blog/2012/03/the-end-of-pagination.html – APC 2012-03-30 22:26:11

+0

感谢您的链接;这是一个有趣的阅读。但是,我没有显示搜索结果。显示的数据量是有限的,数量取决于用户的角色。它有时不止应该放在单个页面上(或者放在JavaScript组件中),尽管我计划在我有时间重新制作UI时转为连续滚动。 – Paul 2012-03-31 01:02:20

回答

1

您可能需要调试了一点,但是却会是这样的:

SELECT * FROM (
    SELECT * FROM (
    SELECT id FROM (
     SELECT id, name, row_number() over (partition by id order by name) rn 
     FROM table1 
     INNER JOIN table2 ON table2.fkid = table1.id 
    ) 
    ) WHERE rn=1 ORDER BY name, id 
) WHERE rownum>=1 and rownum<=4; 
+0

工作完美,速度也很快。非常感谢! – Paul 2012-04-02 18:27:08

0

这是一个有点令人费解(和我往往会怀疑它可以简化),但它应该工作。你可以在WHERE条款中放置任何你想要的开始和结束位置 - 我在这里展示的start = 2和n = 4是从一个单独的表格中提取的,但是可以通过使用几个参数来简化。

SQL> ed 
Wrote file afiedt.buf 

    1 with t as (
    2 select 2 id, 'apple' name from dual union all 
    3 select 23, 'banana' from dual union all 
    4 select 77, 'cranberry' from dual union all 
    5 select 23, 'dark chocolate' from dual union all 
    6 select 8, 'egg' from dual union all 
    7 select 2, 'yak' from dual union all 
    8 select 19, 'zebra' from dual 
    9 ), 
10 x as (
11 select 2 start_pos, 4 n from dual 
12 ) 
13 select * 
14 from (
15  select distinct 
16    id, 
17    dense_rank() over (order by min_id_rnk) outer_rnk 
18  from (
19   select id, 
20     min(rnk) over (partition by id) min_id_rnk 
21   from (
22    select id, 
23      name, 
24      rank() over (order by name) rnk 
25    from t 
26   ) 
27  ) 
28 ) 
29 where outer_rnk between (select start_pos from x) and (select start_pos+n-1 from x) 
30* order by outer_rnk 
SQL>/

     ID OUTER_RNK 
---------- ---------- 
     23   2 
     77   3 
     8   4 
     19   5 
相关问题