В Oracle, как получить страницу с различными значениями из отсортированных результатов? - PullRequest
0 голосов
/ 31 марта 2012

У меня есть 2 столбца в отношении один ко многим.Я хочу отсортировать по «многим» и вернуть первое вхождение «одного».Мне нужно пролистать данные, поэтому, например, мне нужно иметь возможность получить 3-ю группу из 10 уникальных значений "one".

У меня такой запрос:

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 уникальных идентификаторов.Например, если 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)

, который дал мне идентификаторы в числовом порядке, а не в порядкекак имена будут.

Я также попытался:

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)

, но это дало мне повторяющиеся значения.

Как я могу просмотреть результаты этих данных?Мне просто нужны идентификаторы, ничего из таблицы «многие».

update

Полагаю, я все ближе с изменением внутреннего запроса на

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

... но я все еще получаю дубликаты идентификаторов.

Ответы [ 2 ]

1 голос
/ 31 марта 2012

Вам может понадобиться немного отладить его, но это будет примерно так:

  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 голосов
/ 31 марта 2012

Это немного запутанно (и я склонен подозревать, что это можно упростить), но оно должно работать.Вы можете указать любое начальное и конечное положение в предложении 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
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...