xchgeaxeax писал(а):Даже звучит жутко...
исходная диспозиция
- Код: Выделить всё
---------------------------------
pers_t
pers_id pers_fio
1 иванова
2 сидоров
---------------------------------
doc_t
doc_id write_date
1 01.01.2024
---------------------------------
doc_sp_t
pos_id doc_id pers_id
1 1 1
2 1 2
---------------------------------
устраивается петров, иванова меняет фамилию на петрова, документ 1 должен сохранить ссылку на иванову, петрова же для новых документов
- Код: Выделить всё
---------------------------------
pers_t
pers_id pers_fio
1 петрова
2 сидоров
3 петров
---------------------------------
doc_t
doc_id write_date
1 01.01.2024
2 01.01.2025
---------------------------------
doc_sp_t
pos_id doc_id pers_id
1 1 1
2 1 2
3 2 1
4 2 2
5 2 3
---------------------------------
SELECT d.doc_id, d.write_date, sp.pos_id, sp.pers_id, p.pers_fio FROM doc_t d INNER JOIN doc_sp_t sp ON sp.doc_id = d.doc_id INNER JOIN pers_t p ON p.pers_id = sp.pers_id
ORDER BY d.doc_id, sp.pos_id
doc_id write_date pos_id pers_id pers_fio
1 01.01.2024 1 1 петрова
1 01.01.2024 2 2 сидоров
2 01.01.2025 3 1 петрова
2 01.01.2025 4 2 сидоров
2 01.01.2025 5 3 петров
---------------------------------
- Код: Выделить всё
/*
DROP TABLE doc_sp_t
/
DROP TABLE doc_t
/
DROP TABLE pers_t
/
*/
CREATE TABLE pers_t (
pers_id NUMBER PRIMARY KEY,
pers_fio VARCHAR2(1000) NOT NULL
)
/
CREATE TABLE doc_t (
doc_id NUMBER PRIMARY KEY,
write_date DATE NOT NULL
)
/
CREATE TABLE doc_sp_t (
pos_id NUMBER PRIMARY KEY,
doc_id NUMBER NOT NULL REFERENCES doc_t (doc_id),
pers_id NUMBER NOT NULL REFERENCES pers_t (pers_id)
)
/
/*
DELETE FROM doc_sp_t
/
DELETE FROM doc_t
/
DELETE FROM pers_t
/
*/
INSERT INTO pers_t (pers_id, pers_fio)
VALUES (1, 'иванова')
/
INSERT INTO doc_t (doc_id, write_date)
VALUES (1, '01.01.2024')
/
INSERT INTO doc_sp_t (pos_id, doc_id, pers_id)
VALUES (1, 1, 1)
/
INSERT INTO pers_t (pers_id, pers_fio)
VALUES (2, 'сидоров')
/
INSERT INTO doc_sp_t (pos_id, doc_id, pers_id)
VALUES (2, 1, 2)
/
---------------------------------
pers_t
pers_id pers_fio
1 иванова
2 сидоров
---------------------------------
doc_t
doc_id write_date
1 01.01.2024
---------------------------------
doc_sp_t
pos_id doc_id pers_id
1 1 1
2 1 2
---------------------------------
INSERT INTO pers_t (pers_id, pers_fio)
VALUES (3, 'петров')
/
INSERT INTO doc_t (doc_id, write_date)
VALUES (2, '01.01.2025')
/
INSERT INTO doc_sp_t (pos_id, doc_id, pers_id)
VALUES (3, 2, 1)
/
INSERT INTO doc_sp_t (pos_id, doc_id, pers_id)
VALUES (4, 2, 2)
/
INSERT INTO doc_sp_t (pos_id, doc_id, pers_id)
VALUES (5, 2, 3)
/
UPDATE pers_t SET pers_fio = 'петрова' WHERE pers_id = 1
/
---------------------------------
pers_t
pers_id pers_fio
1 петрова
2 сидоров
3 петров
---------------------------------
doc_t
doc_id write_date
1 01.01.2024
2 01.01.2025
---------------------------------
doc_sp_t
pos_id doc_id pers_id
1 1 1
2 1 2
3 2 1
4 2 2
5 2 3
---------------------------------
SELECT d.doc_id, d.write_date, sp.pos_id, sp.pers_id, p.pers_fio FROM doc_t d INNER JOIN doc_sp_t sp ON sp.doc_id = d.doc_id INNER JOIN pers_t p ON p.pers_id = sp.pers_id
ORDER BY d.doc_id, sp.pos_id
doc_id write_date pos_id pers_id pers_fio
1 01.01.2024 1 1 петрова
1 01.01.2024 2 2 сидоров
2 01.01.2025 3 1 петрова
2 01.01.2025 4 2 сидоров
2 01.01.2025 5 3 петров
---------------------------------
Добавлено спустя 7 минут 10 секунд:рассматриваем вариант с ревизиями (а не датами)
ревизия глобальный счетчик
идея в двух полях, начало существования записи (beg_id) и конец существования (end_id), содержащие ревизии.
при создании объекта вставляется запись где в beg_id новая ревизия, в end_id признак отсутствия ограничения существования,
при редактировании объекта вставляется запись аналогично созданию и у записи предыдущей версии заполняется end_id значением согласно beg_id новой,
при удалении объекта заполняется поле end_id последней версии, ограничивая существование.
- Код: Выделить всё
pers_t
vpers_id beg_id end_id pers_id pers_fio
1 1 3(4 п4) 1 иванова
2 2 ? 2 сидоров
3 3 ? 3 петров
4 4 ? 1 петрова
тут возникают неоднозначности, первая, каким должен быть признак отсутствия ограничения существования в end_id, это NULL (п1), это некая максимальная ревизия 999 (п2),
вторая, что конкретно помещать в end_id, ревизию до которой существует включительно (п3) и тогда можно использовать
rev_id BETWEEN beg_id AND end_id или ревизию в которой ее уже не существует (п4) и тогда условие будет rev_id >= beg_id AND rev_id < end_id
п1 - NULL плох всякими OR, NVL, COALESCE, типа rev_id BETWEEN beg_id AND COALESCE(end_id, rev_id)
п2 - 999 плох тем что достигнув его нужно добавить девятку и обновить все объекты отодвинув границу
п3 - плох тем что надо определять end_id для предыдущей версии, нельзя просто из новой ревизии вычесть один 4 - 1 = 3, 3 может не существовать
теряется связанность как в п4 где end_id предыдущей версии содержит ревизию следующей версии - 4
п4 - плох условием rev_id >= beg_id AND rev_id < COALESCE(end_id, rev_id +1) хотя нормальный движек бд должен оптимизировать константы
выбираем п1 и п4
- Код: Выделить всё
rev_t
rev_id
1
2
3
4
---------------------------------
pers_t
vpers_id beg_id end_id pers_id pers_fio
1 1 4 1 иванова
2 2 ? 2 сидоров
3 3 ? 3 петров
4 4 ? 1 петрова
---------------------------------
doc_t
vdoc_id beg_id end_id doc_id write_date
1 1 ? 1 01.01.2024
2 3 ? 2 01.01.2025
---------------------------------
doc_sp_t
vpos_id beg_id end_id pos_id vdoc_id vpers_id
1 1 ? 1 1 1
2 2 ? 2 1 2
3 3 4 3 2 1
4 3 ? 4 2 2
5 3 ? 5 2 3
6 4 ? 3 2 4
---------------------------------
SELECT d.doc_id, d.write_date, sp.pos_id, p.pers_id, p.pers_fio FROM doc_t d INNER JOIN doc_sp_t sp ON sp.vdoc_id = d.vdoc_id INNER JOIN pers_t p ON p.vpers_id = sp.vpers_id, rev_t r
WHERE r.rev_id = 4
AND r.rev_id >= d.beg_id AND r.rev_id < COALESCE(d.end_id, r.rev_id +1)
AND r.rev_id >= sp.beg_id AND r.rev_id < COALESCE(sp.end_id, r.rev_id +1)
ORDER BY d.doc_id, sp.pos_id
doc_id write_date pos_id pers_id pers_fio
1 01.01.2024 1 1 иванова
1 01.01.2024 2 2 сидоров
2 01.01.2025 3 1 петрова
2 01.01.2025 4 2 сидоров
2 01.01.2025 5 3 петров
- Код: Выделить всё
/*
DROP TABLE doc_sp_t
/
DROP TABLE doc_t
/
DROP TABLE pers_t
/
DROP TABLE rev_t
/
*/
CREATE TABLE rev_t (
rev_id NUMBER PRIMARY KEY
)
/
CREATE TABLE pers_t (
vpers_id NUMBER PRIMARY KEY,
beg_id NUMBER NOT NULL REFERENCES rev_t (rev_id),
end_id NUMBER REFERENCES rev_t (rev_id),
pers_id NUMBER NOT NULL,
pers_fio VARCHAR2(1000) NOT NULL
)
/
CREATE INDEX ix_pers_t ON pers_t (beg_id, end_id, pers_id)
/
CREATE TABLE doc_t (
vdoc_id NUMBER PRIMARY KEY,
beg_id NUMBER NOT NULL REFERENCES rev_t (rev_id),
end_id NUMBER REFERENCES rev_t (rev_id),
doc_id NUMBER NOT NULL,
write_date DATE NOT NULL
)
/
CREATE INDEX ix_doc_t ON doc_t (beg_id, end_id, doc_id)
/
CREATE TABLE doc_sp_t (
vpos_id NUMBER PRIMARY KEY,
beg_id NUMBER NOT NULL REFERENCES rev_t (rev_id),
end_id NUMBER REFERENCES rev_t (rev_id),
pos_id NUMBER NOT NULL,
vdoc_id NUMBER NOT NULL REFERENCES doc_t (vdoc_id),
vpers_id NUMBER NOT NULL REFERENCES pers_t (vpers_id)
)
/
CREATE INDEX ix_doc_sp_t ON doc_sp_t (beg_id, end_id, pos_id)
/
/*
DELETE FROM doc_sp_t
/
DELETE FROM doc_t
/
DELETE FROM pers_t
/
DELETE FROM rev_t
/
*/
INSERT INTO rev_t (rev_id)
VALUES (1)
/
INSERT INTO pers_t (vpers_id, beg_id, end_id, pers_id, pers_fio)
VALUES (1, 1, null, 1, 'иванова')
/
INSERT INTO doc_t (vdoc_id, beg_id, end_id, doc_id, write_date)
VALUES (1, 1, null, 1, '01.01.2024')
/
INSERT INTO doc_sp_t (vpos_id, beg_id, end_id, pos_id, vdoc_id, vpers_id)
VALUES (1, 1, null, 1, 1, 1)
/
INSERT INTO rev_t (rev_id)
VALUES (2)
/
INSERT INTO pers_t (vpers_id, beg_id, end_id, pers_id, pers_fio)
VALUES (2, 2, null, 2, 'сидоров')
/
INSERT INTO doc_sp_t (vpos_id, beg_id, end_id, pos_id, vdoc_id, vpers_id)
VALUES (2, 2, null, 2, 1, 2)
/
---------------------------------
rev_t
rev_id
1
2
---------------------------------
pers_t
vpers_id beg_id end_id pers_id pers_fio
1 1 ? 1 иванова
2 2 ? 2 сидоров
---------------------------------
doc_t
vdoc_id beg_id end_id doc_id write_date
1 1 ? 1 01.01.2024
---------------------------------
doc_sp_t
vpos_id beg_id end_id pos_id vdoc_id vpers_id
1 1 ? 1 1 1
2 2 ? 2 1 2
---------------------------------
INSERT INTO rev_t (rev_id)
VALUES (3)
/
INSERT INTO pers_t (vpers_id, beg_id, end_id, pers_id, pers_fio)
VALUES (3, 3, null, 3, 'петров')
/
INSERT INTO doc_t (vdoc_id, beg_id, end_id, doc_id, write_date)
VALUES (2, 3, null, 2, '01.01.2025')
/
INSERT INTO doc_sp_t (vpos_id, beg_id, end_id, pos_id, vdoc_id, vpers_id)
VALUES (3, 3, null, 3, 2, 1)
/
INSERT INTO doc_sp_t (vpos_id, beg_id, end_id, pos_id, vdoc_id, vpers_id)
VALUES (4, 3, null, 4, 2, 2)
/
INSERT INTO doc_sp_t (vpos_id, beg_id, end_id, pos_id, vdoc_id, vpers_id)
VALUES (5, 3, null, 5, 2, 3)
/
INSERT INTO rev_t (rev_id)
VALUES (4)
/
INSERT INTO pers_t (vpers_id, beg_id, end_id, pers_id, pers_fio)
VALUES (4, 4, null, 1, 'петрова')
/
UPDATE pers_t SET end_id = 4 WHERE vpers_id = 1
/
INSERT INTO doc_sp_t (vpos_id, beg_id, end_id, pos_id, vdoc_id, vpers_id)
VALUES (6, 4, null, 3, 2, 4)
/
UPDATE doc_sp_t SET end_id = 4 WHERE vpos_id = 3
/
---------------------------------
rev_t
rev_id
1
2
3
4
---------------------------------
pers_t
vpers_id beg_id end_id pers_id pers_fio
1 1 4 1 иванова
2 2 ? 2 сидоров
3 3 ? 3 петров
4 4 ? 1 петрова
---------------------------------
doc_t
vdoc_id beg_id end_id doc_id write_date
1 1 ? 1 01.01.2024
2 3 ? 2 01.01.2025
---------------------------------
doc_sp_t
vpos_id beg_id end_id pos_id vdoc_id vpers_id
1 1 ? 1 1 1
2 2 ? 2 1 2
3 3 4 3 2 1
4 3 ? 4 2 2
5 3 ? 5 2 3
6 4 ? 3 2 4
---------------------------------
SELECT d.doc_id, d.write_date, sp.pos_id, p.pers_id, p.pers_fio FROM doc_t d INNER JOIN doc_sp_t sp ON sp.vdoc_id = d.vdoc_id INNER JOIN pers_t p ON p.vpers_id = sp.vpers_id
ORDER BY d.doc_id, sp.pos_id
doc_id write_date pos_id pers_id pers_fio
1 01.01.2024 1 1 иванова
1 01.01.2024 2 2 сидоров
2 01.01.2025 3 1 иванова
2 01.01.2025 3 1 петрова
2 01.01.2025 4 2 сидоров
2 01.01.2025 5 3 петров
---------------------------------
SELECT d.doc_id, d.write_date, sp.pos_id, p.pers_id, p.pers_fio FROM doc_t d INNER JOIN doc_sp_t sp ON sp.vdoc_id = d.vdoc_id INNER JOIN pers_t p ON p.vpers_id = sp.vpers_id, rev_t r
WHERE r.rev_id = 4
AND r.rev_id >= d.beg_id AND r.rev_id < COALESCE(d.end_id, r.rev_id +1)
AND r.rev_id >= sp.beg_id AND r.rev_id < COALESCE(sp.end_id, r.rev_id +1)
ORDER BY d.doc_id, sp.pos_id
doc_id write_date pos_id pers_id pers_fio
1 01.01.2024 1 1 иванова
1 01.01.2024 2 2 сидоров
2 01.01.2025 3 1 петрова
2 01.01.2025 4 2 сидоров
2 01.01.2025 5 3 петров
---------------------------------
SELECT d.doc_id, d.write_date, sp.pos_id, p.pers_id, p.pers_fio FROM doc_t d INNER JOIN doc_sp_t sp ON sp.vdoc_id = d.vdoc_id INNER JOIN pers_t p ON p.vpers_id = sp.vpers_id, rev_t r
WHERE r.rev_id = 3
AND r.rev_id >= d.beg_id AND r.rev_id < COALESCE(d.end_id, r.rev_id +1)
AND r.rev_id >= sp.beg_id AND r.rev_id < COALESCE(sp.end_id, r.rev_id +1)
AND d.doc_id = 2
ORDER BY d.doc_id, sp.pos_id
doc_id write_date pos_id pers_id pers_fio
2 01.01.2025 3 1 иванова
2 01.01.2025 4 2 сидоров
2 01.01.2025 5 3 петров
---------------------------------
Добавлено спустя 7 минут 23 секунды:можно объединить поля v*_id и beg_id и получить сквозное версионирование всех изменений внутри одной ревизии
- Код: Выделить всё
/*
DROP TABLE doc_sp_t
/
DROP TABLE doc_t
/
DROP TABLE pers_t
/
DROP TABLE ver_t
/
DROP TABLE rev_t
/
*/
CREATE TABLE rev_t (
rev_id NUMBER PRIMARY KEY,
ver_id NUMBER
)
/
CREATE INDEX ix_rev_t ON rev_t (rev_id, ver_id)
/
CREATE TABLE ver_t (
ver_id NUMBER PRIMARY KEY,
rev_id NUMBER REFERENCES rev_t (rev_id)
)
/
CREATE TABLE pers_t (
vpers_id NUMBER PRIMARY KEY REFERENCES ver_t (ver_id),
end_id NUMBER REFERENCES ver_t (ver_id),
pers_id NUMBER NOT NULL,
pers_fio VARCHAR2(1000) NOT NULL
)
/
CREATE INDEX ix_pers_t ON pers_t (vpers_id, end_id, pers_id)
/
CREATE TABLE doc_t (
vdoc_id NUMBER PRIMARY KEY REFERENCES ver_t (ver_id),
end_id NUMBER REFERENCES ver_t (ver_id),
doc_id NUMBER NOT NULL,
write_date DATE NOT NULL
)
/
CREATE INDEX ix_doc_t ON doc_t (vdoc_id, end_id, doc_id)
/
CREATE TABLE doc_sp_t (
vpos_id NUMBER PRIMARY KEY REFERENCES ver_t (ver_id),
end_id NUMBER REFERENCES ver_t (ver_id),
pos_id NUMBER NOT NULL,
vdoc_id NUMBER NOT NULL REFERENCES doc_t (vdoc_id),
vpers_id NUMBER NOT NULL REFERENCES pers_t (vpers_id)
)
/
CREATE INDEX ix_doc_sp_t ON doc_sp_t (vpos_id, end_id, pos_id)
/
/*
DELETE FROM doc_sp_t
/
DELETE FROM doc_t
/
DELETE FROM pers_t
/
DELETE FROM ver_t
/
DELETE FROM rev_t
/
*/
INSERT INTO rev_t (rev_id)
VALUES (1)
/
INSERT INTO ver_t (ver_id, rev_id)
VALUES (1, 1)
/
INSERT INTO pers_t (vpers_id, end_id, pers_id, pers_fio)
VALUES (1, null, 1, 'иванова')
/
INSERT INTO ver_t (ver_id, rev_id)
VALUES (2, 1)
/
INSERT INTO doc_t (vdoc_id, end_id, doc_id, write_date)
VALUES (2, null, 1, '01.01.2024')
/
INSERT INTO rev_t (rev_id)
VALUES (2)
/
INSERT INTO ver_t (ver_id, rev_id)
VALUES (3, 2)
/
INSERT INTO doc_sp_t (vpos_id, end_id, pos_id, vdoc_id, vpers_id)
VALUES (3, null, 1, 2, 1)
/
INSERT INTO ver_t (ver_id, rev_id)
VALUES (4, 2)
/
INSERT INTO pers_t (vpers_id, end_id, pers_id, pers_fio)
VALUES (4, null, 2, 'сидоров')
/
INSERT INTO ver_t (ver_id, rev_id)
VALUES (5, 2)
/
INSERT INTO doc_sp_t (vpos_id, end_id, pos_id, vdoc_id, vpers_id)
VALUES (5, null, 2, 2, 4)
/
---------------------------------
rev_t
rev_id
1
2
---------------------------------
pers_t
vpers_id end_id pers_id pers_fio
1 ? 1 иванова
4 ? 2 сидоров
---------------------------------
doc_t
vdoc_id end_id doc_id write_date
2 ? 1 01.01.2024
---------------------------------
doc_sp_t
vpos_id end_id pos_id vdoc_id vpers_id
3 ? 1 2 1
5 ? 2 2 4
---------------------------------
INSERT INTO rev_t (rev_id)
VALUES (3)
/
INSERT INTO ver_t (ver_id, rev_id)
VALUES (6, 3)
/
INSERT INTO pers_t (vpers_id, end_id, pers_id, pers_fio)
VALUES (6, null, 3, 'петров')
/
INSERT INTO ver_t (ver_id, rev_id)
VALUES (7, 3)
/
INSERT INTO doc_t (vdoc_id, end_id, doc_id, write_date)
VALUES (7, null, 2, '01.01.2025')
/
INSERT INTO ver_t (ver_id, rev_id)
VALUES (8, 3)
/
INSERT INTO doc_sp_t (vpos_id, end_id, pos_id, vdoc_id, vpers_id)
VALUES (8, null, 3, 7, 1)
/
INSERT INTO ver_t (ver_id, rev_id)
VALUES (9, 3)
/
INSERT INTO doc_sp_t (vpos_id, end_id, pos_id, vdoc_id, vpers_id)
VALUES (9, null, 4, 7, 4)
/
INSERT INTO ver_t (ver_id, rev_id)
VALUES (10, 3)
/
INSERT INTO doc_sp_t (vpos_id, end_id, pos_id, vdoc_id, vpers_id)
VALUES (10, null, 5, 7, 6)
/
UPDATE rev_t SET ver_id = 10 WHERE rev_id = 3
/
INSERT INTO rev_t (rev_id)
VALUES (4)
/
INSERT INTO ver_t (ver_id, rev_id)
VALUES (11, 4)
/
INSERT INTO pers_t (vpers_id, end_id, pers_id, pers_fio)
VALUES (11, null, 1, 'петрова')
/
UPDATE pers_t SET end_id = 11 WHERE vpers_id = 1
/
INSERT INTO ver_t (ver_id, rev_id)
VALUES (12, 4)
/
INSERT INTO doc_sp_t (vpos_id, end_id, pos_id, vdoc_id, vpers_id)
VALUES (12, null, 3, 7, 11)
/
UPDATE doc_sp_t SET end_id = 12 WHERE vpos_id = 8
/
UPDATE rev_t SET ver_id = 12 WHERE rev_id = 4
/
---------------------------------
rev_t
rev_id
1
2
3
4
---------------------------------
pers_t
vpers_id end_id pers_id pers_fio
1 11 1 иванова
4 ? 2 сидоров
6 ? 3 петров
11 ? 1 петрова
---------------------------------
doc_t
vdoc_id end_id doc_id write_date
2 ? 1 01.01.2024
7 ? 2 01.01.2025
---------------------------------
doc_sp_t
vpos_id end_id pos_id vdoc_id vpers_id
3 ? 1 2 1
5 ? 2 2 4
8 12 3 7 1
9 ? 4 7 4
10 ? 5 7 6
12 ? 3 7 11
---------------------------------
SELECT d.doc_id, d.write_date, sp.pos_id, p.pers_id, p.pers_fio FROM doc_t d INNER JOIN doc_sp_t sp ON sp.vdoc_id = d.vdoc_id INNER JOIN pers_t p ON p.vpers_id = sp.vpers_id
ORDER BY d.doc_id, sp.pos_id
doc_id write_date pos_id pers_id pers_fio
1 01.01.2024 1 1 иванова
1 01.01.2024 2 2 сидоров
2 01.01.2025 3 1 иванова
2 01.01.2025 3 1 петрова
2 01.01.2025 4 2 сидоров
2 01.01.2025 5 3 петров
---------------------------------
SELECT d.doc_id, d.write_date, sp.pos_id, p.pers_id, p.pers_fio FROM doc_t d INNER JOIN doc_sp_t sp ON sp.vdoc_id = d.vdoc_id INNER JOIN pers_t p ON p.vpers_id = sp.vpers_id, rev_t r
WHERE r.rev_id = 4
AND r.ver_id >= d.vdoc_id AND r.ver_id < COALESCE(d.end_id, r.ver_id +1)
AND r.ver_id >= sp.vpos_id AND r.ver_id < COALESCE(sp.end_id, r.ver_id +1)
ORDER BY d.doc_id, sp.pos_id
doc_id write_date pos_id pers_id pers_fio
1 01.01.2024 1 1 иванова
1 01.01.2024 2 2 сидоров
2 01.01.2025 3 1 петрова
2 01.01.2025 4 2 сидоров
2 01.01.2025 5 3 петров
---------------------------------
SELECT d.doc_id, d.write_date, sp.pos_id, p.pers_id, p.pers_fio FROM doc_t d INNER JOIN doc_sp_t sp ON sp.vdoc_id = d.vdoc_id INNER JOIN pers_t p ON p.vpers_id = sp.vpers_id, rev_t r
WHERE r.rev_id = 3
AND r.ver_id >= d.vdoc_id AND r.ver_id < COALESCE(d.end_id, r.ver_id +1)
AND r.ver_id >= sp.vpos_id AND r.ver_id < COALESCE(sp.end_id, r.ver_id +1)
AND d.doc_id = 2
ORDER BY d.doc_id, sp.pos_id
doc_id write_date pos_id pers_id pers_fio
2 01.01.2025 3 1 иванова
2 01.01.2025 4 2 сидоров
2 01.01.2025 5 3 петров
---------------------------------
Добавлено спустя 3 минуты 8 секунд:выбираем п2 и п3, поля v*_id и beg_id объединены
- Код: Выделить всё
/*
DROP TABLE doc_sp_t
/
DROP TABLE doc_t
/
DROP TABLE pers_t
/
DROP TABLE ver_t
/
DROP TABLE rev_t
/
*/
CREATE TABLE rev_t (
rev_id NUMBER PRIMARY KEY,
ver_id NUMBER
)
/
CREATE INDEX ix_rev_t ON rev_t (rev_id, ver_id)
/
CREATE TABLE ver_t (
ver_id NUMBER PRIMARY KEY,
rev_id NUMBER REFERENCES rev_t (rev_id)
)
/
CREATE TABLE pers_t (
vpers_id NUMBER PRIMARY KEY REFERENCES ver_t (ver_id),
end_id NUMBER NOT NULL REFERENCES ver_t (ver_id),
pers_id NUMBER NOT NULL,
pers_fio VARCHAR2(1000) NOT NULL
)
/
CREATE INDEX ix_pers_t ON pers_t (vpers_id, end_id, pers_id)
/
CREATE TABLE doc_t (
vdoc_id NUMBER PRIMARY KEY REFERENCES ver_t (ver_id),
end_id NUMBER NOT NULL REFERENCES ver_t (ver_id),
doc_id NUMBER NOT NULL,
write_date DATE NOT NULL
)
/
CREATE INDEX ix_doc_t ON doc_t (vdoc_id, end_id, doc_id)
/
CREATE TABLE doc_sp_t (
vpos_id NUMBER PRIMARY KEY REFERENCES ver_t (ver_id),
end_id NUMBER NOT NULL REFERENCES ver_t (ver_id),
pos_id NUMBER NOT NULL,
vdoc_id NUMBER NOT NULL REFERENCES doc_t (vdoc_id),
vpers_id NUMBER NOT NULL REFERENCES pers_t (vpers_id)
)
/
CREATE INDEX ix_doc_sp_t ON doc_sp_t (vpos_id, end_id, pos_id)
/
/*
DELETE FROM doc_sp_t
/
DELETE FROM doc_t
/
DELETE FROM pers_t
/
DELETE FROM ver_t
/
DELETE FROM rev_t
/
*/
INSERT INTO rev_t (rev_id)
VALUES (1)
/
INSERT INTO ver_t (ver_id, rev_id)
VALUES (999, 1)
/
INSERT INTO ver_t (ver_id, rev_id)
VALUES (1, 1)
/
INSERT INTO pers_t (vpers_id, end_id, pers_id, pers_fio)
VALUES (1, 999, 1, 'иванова')
/
INSERT INTO ver_t (ver_id, rev_id)
VALUES (2, 1)
/
INSERT INTO doc_t (vdoc_id, end_id, doc_id, write_date)
VALUES (2, 999, 1, '01.01.2024')
/
UPDATE rev_t SET ver_id = 2 WHERE rev_id = 1
/
INSERT INTO rev_t (rev_id)
VALUES (2)
/
INSERT INTO ver_t (ver_id, rev_id)
VALUES (3, 2)
/
INSERT INTO doc_sp_t (vpos_id, end_id, pos_id, vdoc_id, vpers_id)
VALUES (3, 999, 1, 2, 1)
/
INSERT INTO ver_t (ver_id, rev_id)
VALUES (4, 2)
/
INSERT INTO pers_t (vpers_id, end_id, pers_id, pers_fio)
VALUES (4, 999, 2, 'сидоров')
/
INSERT INTO ver_t (ver_id, rev_id)
VALUES (5, 2)
/
INSERT INTO doc_sp_t (vpos_id, end_id, pos_id, vdoc_id, vpers_id)
VALUES (5, 999, 2, 2, 4)
/
UPDATE rev_t SET ver_id = 5 WHERE rev_id = 2
/
---------------------------------
rev_t
rev_id
1
2
---------------------------------
pers_t
vpers_id end_id pers_id pers_fio
1 999 1 иванова
4 999 2 сидоров
---------------------------------
doc_t
vdoc_id end_id doc_id write_date
2 999 1 01.01.2024
---------------------------------
doc_sp_t
vpos_id end_id pos_id vdoc_id vpers_id
3 999 1 2 1
5 999 2 2 4
---------------------------------
INSERT INTO rev_t (rev_id)
VALUES (3)
/
INSERT INTO ver_t (ver_id, rev_id)
VALUES (6, 3)
/
INSERT INTO pers_t (vpers_id, end_id, pers_id, pers_fio)
VALUES (6, 999, 3, 'петров')
/
INSERT INTO ver_t (ver_id, rev_id)
VALUES (7, 3)
/
INSERT INTO doc_t (vdoc_id, end_id, doc_id, write_date)
VALUES (7, 999, 2, '01.01.2025')
/
INSERT INTO ver_t (ver_id, rev_id)
VALUES (8, 3)
/
INSERT INTO doc_sp_t (vpos_id, end_id, pos_id, vdoc_id, vpers_id)
VALUES (8, 999, 3, 7, 1)
/
INSERT INTO ver_t (ver_id, rev_id)
VALUES (9, 3)
/
INSERT INTO doc_sp_t (vpos_id, end_id, pos_id, vdoc_id, vpers_id)
VALUES (9, 999, 4, 7, 4)
/
INSERT INTO ver_t (ver_id, rev_id)
VALUES (10, 3)
/
INSERT INTO doc_sp_t (vpos_id, end_id, pos_id, vdoc_id, vpers_id)
VALUES (10, 999, 5, 7, 6)
/
UPDATE rev_t SET ver_id = 10 WHERE rev_id = 3
/
INSERT INTO rev_t (rev_id)
VALUES (4)
/
INSERT INTO ver_t (ver_id, rev_id)
VALUES (11, 4)
/
INSERT INTO pers_t (vpers_id, end_id, pers_id, pers_fio)
VALUES (11, 999, 1, 'петрова')
/
UPDATE pers_t SET end_id = 10 WHERE vpers_id = 1
/
INSERT INTO ver_t (ver_id, rev_id)
VALUES (12, 4)
/
INSERT INTO doc_sp_t (vpos_id, end_id, pos_id, vdoc_id, vpers_id)
VALUES (12, 999, 3, 7, 11)
/
UPDATE doc_sp_t SET end_id = 11 WHERE vpos_id = 8
/
UPDATE rev_t SET ver_id = 12 WHERE rev_id = 4
/
---------------------------------
rev_t
rev_id
1
2
3
4
---------------------------------
pers_t
vpers_id end_id pers_id pers_fio
1 10 1 иванова
4 999 2 сидоров
6 999 3 петров
11 999 1 петрова
---------------------------------
doc_t
vdoc_id end_id doc_id write_date
2 999 1 01.01.2024
7 999 2 01.01.2025
---------------------------------
doc_sp_t
vpos_id end_id pos_id vdoc_id vpers_id
3 999 1 2 1
5 999 2 2 4
8 11 3 7 1
9 999 4 7 4
10 999 5 7 6
12 999 3 7 11
---------------------------------
SELECT d.doc_id, d.write_date, sp.pos_id, p.pers_id, p.pers_fio FROM doc_t d INNER JOIN doc_sp_t sp ON sp.vdoc_id = d.vdoc_id INNER JOIN pers_t p ON p.vpers_id = sp.vpers_id
ORDER BY d.doc_id, sp.pos_id
doc_id write_date pos_id pers_id pers_fio
1 01.01.2024 1 1 иванова
1 01.01.2024 2 2 сидоров
2 01.01.2025 3 1 иванова
2 01.01.2025 3 1 петрова
2 01.01.2025 4 2 сидоров
2 01.01.2025 5 3 петров
---------------------------------
SELECT d.doc_id, d.write_date, sp.pos_id, p.pers_id, p.pers_fio FROM doc_t d INNER JOIN doc_sp_t sp ON sp.vdoc_id = d.vdoc_id INNER JOIN pers_t p ON p.vpers_id = sp.vpers_id, rev_t r
WHERE r.rev_id = 4
AND r.ver_id BETWEEN d.vdoc_id AND d.end_id
AND r.ver_id BETWEEN sp.vpos_id AND sp.end_id
ORDER BY d.doc_id, sp.pos_id
doc_id write_date pos_id pers_id pers_fio
1 01.01.2024 1 1 иванова
1 01.01.2024 2 2 сидоров
2 01.01.2025 3 1 петрова
2 01.01.2025 4 2 сидоров
2 01.01.2025 5 3 петров
---------------------------------
SELECT d.doc_id, d.write_date, sp.pos_id, p.pers_id, p.pers_fio FROM doc_t d INNER JOIN doc_sp_t sp ON sp.vdoc_id = d.vdoc_id INNER JOIN pers_t p ON p.vpers_id = sp.vpers_id, rev_t r
WHERE r.rev_id = 3
AND r.ver_id BETWEEN d.vdoc_id AND d.end_id
AND r.ver_id BETWEEN sp.vpos_id AND sp.end_id
AND d.doc_id = 2
ORDER BY d.doc_id, sp.pos_id
doc_id write_date pos_id pers_id pers_fio
2 01.01.2025 3 1 иванова
2 01.01.2025 4 2 сидоров
2 01.01.2025 5 3 петров
---------------------------------
Добавлено спустя 20 минут 20 секунд:скрипты оракл