Написание представления SQL в Oracle, которое возвращает несколько строк для каждой строки в другой таблице - PullRequest
0 голосов
/ 18 декабря 2011

У меня есть таблица с двумя соответствующими столбцами, идентификатором и VARRAY с двойными числами, представляющими координаты, подобные этой: (x1, y1, x2, y2, x3, y3, ...).Длина этого массива варьируется от четырех до десятков.

Мне нужно написать представление, которое берет все эти строки и расширяет каждую из них в несколько строк с полем порядка, например:

ID order  X   Y
 1   1    x1  y1
 1   2    x2  y2
 1   3    x3  y3
 2   1    x1  y1
 2   2    x2  y2
 2   3    x3  y3

Google не помогает, и, будучи кем-то посредственным в SQL (и в основном в PostgreSQL), в документации Oracle невозможно найти более сложные вещи.

Ответы [ 3 ]

2 голосов
/ 18 декабря 2011

Я для себя люблю таблицы с контурами, вот решение, которое его использует:

create or replace type my_res_typ as object
(
  v_id    number,
  v_order number,
  x       number,
  y       number
)
;
/

CREATE OR REPLACE TYPE my_res_tab AS TABLE OF my_res_typ;
/

create or replace function get_coordinates return my_res_tab
  pipelined is

  Result my_res_typ := my_res_typ(null, null, null, null);
  seq    number;
  i      integer;
begin

  for r in (select * from my_table) loop
    seq := 1;

    i := r.coordinates.first;
    while i < r.coordinates.last loop
      Result.v_id    := r.id;
      Result.v_order := seq;
      Result.x       := r.coordinates(i);
      Result.y       := r.coordinates(i + 1);

      pipe row(Result);
      seq := seq + 1;
      i   := i + 2;
    end loop;

  end loop;

  return;
end get_coordinates;
/

теперь вы можете запросить его так:

select * from table(get_coordinates);

Я использовал

my_table

в качестве имени таблицы

0 голосов
/ 20 декабря 2011

Ниже приведен пример, в котором используются аналитические функции наряду с функцией table для получения нужного набора данных без использования хранимой процедуры.

CREATE OR REPLACE TYPE number_list AS VARRAY(10) OF NUMBER
/

CREATE TABLE my_table(id NUMBER, coordinates number_list)
/

INSERT INTO my_table(id, coordinates)
VALUES     (1, number_list(4,5,6,7,8,9));

INSERT INTO my_table(id, coordinates)
VALUES     (2, number_list(10,11,12,13,14,15));

SELECT   id,
         coordinateset,
         SUM(CASE suborder WHEN 1 THEN coordinate ELSE NULL END) AS x,
         SUM(CASE suborder WHEN 2 THEN coordinate ELSE NULL END) AS y
FROM     (SELECT id,
                 coordinate,
                 DENSE_RANK() OVER (PARTITION BY id ORDER BY CEIL(roworder / 2)) AS coordinateset,
                 DENSE_RANK() OVER (PARTITION BY id, CEIL(roworder / 2) ORDER BY roworder) AS suborder
          FROM   (SELECT a.id, b.COLUMN_VALUE AS coordinate, ROWNUM AS roworder
                  FROM   my_table a, table(coordinates) b))
GROUP BY id, coordinateset
ORDER BY id, coordinateset;

Использование ROWNUM - это единственное, что яЯ немного неуверен в.Хотя в контролируемой среде, кажется, всегда используется порядок, обозначенный varray, я не уверен, что такое поведение гарантировано.

Наконец, чтобы заявить очевидное, это очень плохойдизайн.Даже если вы настроены против использования правильного реляционного дизайна разделения данных на две таблицы, вам все равно будет лучше иметь varray пользовательских типов, которые конкретно указывают, какие значения x и y принадлежат друг другу.

0 голосов
/ 18 декабря 2011

Это можно сделать с помощью оператора PIVOT в sql.Вот несколько ссылок: http://blogs.msdn.com/b/spike/archive/2009/03/03/pivot-tables-in-sql-server-a-simple-sample.aspx http://msdn.microsoft.com/en-us/library/ms177410.aspx позаботьтесь

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...