Sql 在Oracle中,如何从排序结果中获取包含不同值的页面?

Sql 在Oracle中,如何从排序结果中获取包含不同值的页面?,sql,oracle,Sql,Oracle,我在一对多关系中有两列。我想对多个进行排序,并返回第一个出现的一个。我需要翻页查看数据,例如,我需要能够获得第三组10个唯一值 我有这样一个问题: SELECT id, name FROM table1 INNER JOIN table2 ON table2.fkid = table1.id ORDER BY name, id; id | name ---------------- 2 | apple 23 | banana 77 | cranberry

我在一对多关系中有两列。我想对多个进行排序,并返回第一个出现的一个。我需要翻页查看数据,例如,我需要能够获得第三组10个唯一值

我有这样一个问题:

SELECT id, name
FROM table1
INNER JOIN table2 ON table2.fkid = table1.id
ORDER BY name, id;
  id   |  name
----------------
   2   | apple
  23   | banana
  77   | cranberry
  23   | dark chocolate
   8   | egg
   2   | yak
  19   | zebra
  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;
对于表1中的每一行,表2中可以有多行

我的查询结果如下所示:

SELECT id, name
FROM table1
INNER JOIN table2 ON table2.fkid = table1.id
ORDER BY name, id;
  id   |  name
----------------
   2   | apple
  23   | banana
  77   | cranberry
  23   | dark chocolate
   8   | egg
   2   | yak
  19   | zebra
  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;
我需要一页一页地浏览结果集,每个页面包含n个唯一的ID。例如,如果start=1,n=4,我想返回

 2
23
77
 8
按照它们的排序顺序,即名称,其中id返回到其第一次出现的位置。同样,如果start=3,n=4,order=desc,我希望

 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 id, name
FROM table1
INNER JOIN table2 ON table2.fkid = table1.id
ORDER BY name, id;
  id   |  name
----------------
   2   | apple
  23   | banana
  77   | cranberry
  23   | dark chocolate
   8   | egg
   2   | yak
  19   | zebra
  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;

它有点复杂,我倾向于怀疑它可以简化,但它应该可以工作。你可以在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

如果需要对结果进行分页,则应用程序的搜索功能可能已损坏。阅读杰夫·阿特伍德(Jeff Atwood)最近在该教区的博客:感谢链接;这是一本有趣的书。但是,我没有显示搜索结果。显示的数据数量有限,数量取决于用户的角色。有时候,它不仅仅是一个页面上的滚动,或者是一个JavaScript组件中的滚动,尽管我的计划是在有时间重新设计UI时转向连续滚动。工作非常完美,速度也很快。非常感谢!