М.б. и извращения, делать вычисления в SQL, но...
В общем, экспериментирую по цепочке точек (траектории) посчитать углы поворота в каждой.

Осталось из VIEW с посчитанными углами перенести данные обратно в таблицу точек.
И хочется это красиво, пересечением множеств :-)

Обе СУБД MS SQL и Firebird поддерживают обычный синтаксис оператора UPDATE. СУБД MS SQL также поддерживает синтаксис оператора UPDATE, в котором выполняется соединение (join) и производится обновление одной из таблиц соединения. Можно думать об этом как об условии WHERE на стероидах. Если такая функция очень нужна, то ее можно реализовать в СУБД Firebird с использованием представлений (views).

Речь про
update table1
set table1.column1 = table2.column2
  from table2 where .....

Написана в целом логичная вещь, за парой исключений.
Во первых VIEW вещь глобальная и напрваление "каждому запросу свою вьюху" настораживает
Во-вторых, что, если источник данных - тоже VIEW с вычислениями?

Поскольку VIEW увы не умеет быть частично обновляемый (относительно одних
столбцов, но не других), то не проходит например

CREATE OR ALTER VIEW UPDATE_METRICS(
      IDX,  ANGLE,  TURN)
AS
select t.idx, v.angle, t.turn
  from metrics t, vector_angles_deg v where v.metrics_idx = t.idx
-----
update update_metrics set turn=angle
-----
Unsuccessful execution caused by system error that does not preclude
successful execution of subsequent statements.
Attempt to execute an unprepared dynamic SQL statement.

=========================

обвязывать VIEW триггерами не интересно - тогда проще процедуру или execute block сделать.
с курсором, императивно.
но ведь не красиво перебирать курсором....

==========================

"Лобовое" update metrics set turn = (select angle from vector_angles_deg
where metrics_idx = idx)
тоже некрасиво, императивненько. Да и выдаёт 42 чтения VECTORS на 7 обновлённых строк в METRICS

PLAN JOIN (VECTOR_ANGLES_DEG VECTOR_ANGLES_RAD VECTOR_COSINES Q INDEX (PK_VECTORS), VECTOR_ANGLES_DEG VECTOR_ANGLES_RAD VECTOR_COSINES P INDEX (FK_VECTORS_1))
PLAN (METRICS NATURAL)

Приятный "декларативный" бонус - обновляются все точки, в том числе первая и последняя, где никакuх углов нет: они заполняются NULL

===========================

execute block as
declare variable id integer;
declare variable an double precision;
begin
 for select angle, metrics_idx from vector_angles_deg into :an, :id
 do  update metrics set turn = :an where idx = :id;
end;

Жуть некрасивая. Зато какой хороший план, всего 5+6 чтений на 5 обновлений.
Правда не заNULLяются остальные 2 строки metrics, придётся отдельно их заранее чистить, без фильтрации или с неэффективной фильтрацией where not exists.
Но всё-равно не n^2 !

PLAN (METRICS INDEX (PK_METRICS))
PLAN JOIN (VECTOR_ANGLES_DEG VECTOR_ANGLES_RAD VECTOR_COSINES P NATURAL, VECTOR_ANGLES_DEG VECTOR_ANGLES_RAD VECTOR_COSINES Q INDEX (PK_VECTORS))

PS: С курсором не делал, но результат, думаю, будет идентичен.

==============

Хорошая штука UPDATE с JOIN'ом :-)




Ну и напоследок - с чем разлекался.

Данные:
 insert into layers values (1, 1, null);
 insert into objects values (1,1,1,1,1, null);

 insert into metrics values (1,   0,3  ,1,null);
 insert into metrics values (2,   0,0  ,1,null);
 insert into metrics values (3,  -4,0  ,1,null);
 insert into metrics values (4,  -5,1  ,1,null);
 insert into metrics values (5,  -6,1  ,1,null);
 insert into metrics values (6,  -7,1  ,1,null);
 insert into metrics values (7,  -6,1  ,1,null);

 execute procedure make_vectors;


Cтруктура:

CREATE GLOBAL TEMPORARY TABLE LAYERS (
    IDX     INTEGER NOT NULL,
    NUMBER  INTEGER NOT NULL,
    NAME    VARCHAR(200)
) ON COMMIT DELETE ROWS;


CREATE GLOBAL TEMPORARY TABLE METRICS (
    IDX     INTEGER NOT NULL,
    X       INTEGER NOT NULL,
    Y       INTEGER NOT NULL,
    OBJECT  INTEGER NOT NULL,
    TURN    DOUBLE PRECISION
) ON COMMIT DELETE ROWS;


CREATE GLOBAL TEMPORARY TABLE OBJECTS (
    IDX        INTEGER NOT NULL,
    LAYER      SMALLINT NOT NULL,
    OBJTYPE    SMALLINT NOT NULL,
    NUMBER     SMALLINT NOT NULL,
    CODE       INTEGER NOT NULL,
    SEMANTICS  BLOB SUB_TYPE 1 SEGMENT SIZE 80
) ON COMMIT DELETE ROWS;


CREATE GLOBAL TEMPORARY TABLE VECTORS (
    IDX     INTEGER NOT NULL,
    X       INTEGER NOT NULL,
    Y       INTEGER NOT NULL,
    OBJECT  INTEGER NOT NULL,
    LEN     DOUBLE PRECISION NOT NULL
) ON COMMIT DELETE ROWS;


ALTER TABLE LAYERS ADD CONSTRAINT PK_LAYERS PRIMARY KEY (IDX);
ALTER TABLE METRICS ADD CONSTRAINT PK_METRICS PRIMARY KEY (IDX);
ALTER TABLE OBJECTS ADD CONSTRAINT PK_OBJECTS PRIMARY KEY (IDX);
ALTER TABLE VECTORS ADD CONSTRAINT PK_VECTORS PRIMARY KEY (IDX);

ALTER TABLE LAYERS ADD CONSTRAINT UQ_LAYERS_NUM UNIQUE (NUMBER);
ALTER TABLE OBJECTS ADD CONSTRAINT UQ_OBJECTS UNIQUE (NUMBER);

ALTER TABLE VECTORS ADD CONSTRAINT FK_VECTORS_1 FOREIGN KEY (OBJECT) REFERENCES OBJECTS (NUMBER); ALTER TABLE VECTORS ADD CONSTRAINT FK_VECTORS_2 FOREIGN KEY (IDX) REFERENCES METRICS (IDX); ALTER TABLE METRICS ADD CONSTRAINT FK_METRICS_1 FOREIGN KEY (OBJECT) REFERENCES OBJECTS (NUMBER); ALTER TABLE OBJECTS ADD CONSTRAINT FK_OBJECTS_1 FOREIGN KEY (LAYER) REFERENCES LAYERS (NUMBER);


SET TERM ^ ;

CREATE OR ALTER TRIGGER CALC_VECTOR_LEN FOR VECTORS
ACTIVE BEFORE INSERT POSITION 0
AS
begin
  NEW.LEN = SQRT(NEW.X*NEW.X + NEW.Y*NEW.Y);
end
^

SET TERM ; ^

/******************************************************************************/
/*** Views ***/
/******************************************************************************/


/* View: VECTOR_COSINES */
CREATE OR ALTER VIEW VECTOR_COSINES(
    METRICS_IDX,
    COSINE_VALUE)
AS
select q.idx,
   (p.x*q.x + p.y*q.y) / (p.len * q.len) as CosValue
from vectors p, vectors q
where q.idx = p.idx+1 and q.object = p.object
;



/* View: VECTOR_ANGLES_RAD */
CREATE OR ALTER VIEW VECTOR_ANGLES_RAD(
    METRICS_IDX,
    ANGLE)
AS
select metrics_idx, acos(cosine_value)
from vector_cosines
;



/* View: VECTOR_ANGLES_DEG */
CREATE OR ALTER VIEW VECTOR_ANGLES_DEG(
    METRICS_IDX,
    ANGLE)
AS
select metrics_idx, angle*180/PI()
from vector_angles_rad
;


/* View: VECTOR_SCALAR_PRODUCTS */
CREATE OR ALTER VIEW VECTOR_SCALAR_PRODUCTS(
    METRICS_IDX,
    PRODUCT)
AS
select p.idx, p.x*q.x + p.y*q.y
from vectors p, vectors q
where q.idx = p.idx+1 and q.object = p.object
;




/******************************************************************************/
/*** Stored Procedures ***/
/******************************************************************************/


SET TERM ^ ;

CREATE OR ALTER PROCEDURE MAKE_VECTORS
AS
begin
 delete from vectors;

 insert into vectors(idx, object, x, y)
   select u.idx, u.object, u.x - v.x, u.y - v.y
           from metrics u, metrics v
   where v.idx = u.idx+1 and u.object = v.object;
end^



SET TERM ; ^


--
Написано в почтовом клиенте браузера Opera: http://www.opera.com/mail/

Ответить