Возможно ли решить систему линейных уравнений запросом?
Дано:
— таблица А с тремя полями: номер строки, номер столбца, коэффициент
— таблица Б с двумя полями: номер строки, свободный член
— все значения заполнены
— система имеет единственное решение
Требуется:
вывести набор данных из двух столбцов: номер переменной, значение.
Текст запроса не должен зависеть от количества переменных. Без использования процедурных расширений SQL. Один запрос SELECT ...
Здравствуйте, naf2000, Вы писали:
N>Возможно ли решить систему линейных уравнений запросом? N>Дано: N>- таблица А с тремя полями: номер строки, номер столбца, коэффициент N>- таблица Б с двумя полями: номер строки, свободный член N>- все значения заполнены N>- система имеет единственное решение N>Требуется: N>вывести набор данных из двух столбцов: номер переменной, значение. N>Текст запроса не должен зависеть от количества переменных. Без использования процедурных расширений SQL. Один запрос SELECT ...
Здравствуйте, rus blood, Вы писали:
RB>И не надо делать рекурсию. RB>Есть таблица B, которая дает размер матрицы и позволяет организовать счетчики.
Было бы интересно увидеть реализацию нахождения определителя произвольного размера на SQL. :]
Здравствуйте, lost_guadelenn, Вы писали:
_>Здравствуйте, rus blood, Вы писали:
RB>>И не надо делать рекурсию. RB>>Есть таблица B, которая дает размер матрицы и позволяет организовать счетчики. _>Было бы интересно увидеть реализацию нахождения определителя произвольного размера на SQL. :]
Методом Гаусса?
Здравствуйте, naf2000, Вы писали:
N>Возможно ли решить систему линейных уравнений запросом? N>Дано: N>- таблица А с тремя полями: номер строки, номер столбца, коэффициент N>- таблица Б с двумя полями: номер строки, свободный член N>- все значения заполнены N>- система имеет единственное решение N>Требуется: N>вывести набор данных из двух столбцов: номер переменной, значение. N>Текст запроса не должен зависеть от количества переменных. Без использования процедурных расширений SQL. Один запрос SELECT ...
У меня чуть-чуть получилось.
СУБД — Oracle 10g Express. Метод Крамера для решения системы + метод Лейбница для нахождения детерминанта.
К сожелению получилось не очень производительное решение. Для размеров меньше 7 находит решение меньше чем за секунду. Для n=7 ~ примерно за 2 с половиной минуты. БОльшие размерности не осиливает.
create table matrix(nrow integer, ncol integer, val number);
create table coef(nrow integer, val number);
with mrank as
(
select count(*) as r
from coef
),
rankgenerator as
(
select rownum as rn
from dual, mrank
connect by level <= mrank.r
),
matrixfordeterminant as
(
select rg.rn, matrix.nrow, matrix.ncol,
case
when rg.rn = matrix.ncol then coef.val
else matrix.val
end as val
from matrix
inner join coef on matrix.nrow = coef.nrow
cross join
(
select rankgenerator.rn from rankgenerator
union all
select 0 from dual
) rg
),
lengthcount as
(
select sum(length(rn)) + count(rn) lencnt
from rankgenerator
),
permutations as
(
select trim('/' from p) path
from
(
select sys_connect_by_path (rn, '/') p
from rankgenerator
connect by nocycle prior rn != rn
) gen, lengthcount
where length(p) = lengthcount.lencnt
),
permutationselements as
(
select perm.path, rn.rn, to_number(regexp_substr(perm.path, '[^/]+', 1, rn.rn)) el
from permutations perm
cross join
(
select rownum as rn from dual, mrank connect by level <= mrank.r
) rn
),
permutation_sign as
(
select permutations.path,
case
when
mod
(
sum(permelem_rightmincount.rightmincount),
2
) = 0
then 1
else -1
end as psign
from permutations inner join
(
select outer.path,
(
select count(*)
from permutationselements inn
where inn.path = outer.path
and inn.rn > outer.rn
and inn.el < outer.el
) rightmincount
from permutationselements outer
) permelem_rightmincount
on permutations.path = permelem_rightmincount.path
group by permutations.path
),
determinants as
(
select rn, sum(mul *
(case when mod(msign, 2) = 0 then 1 else -1 end) *
(case when mzero > 0 then 0 else 1 end)) det
from
(
select matrixfordeterminant.rn,
permutation_sign.psign*exp(sum(ln(abs(case when matrixfordeterminant.val = 0
then 0.01
else matrixfordeterminant.val
end)))) mul,
sum(case when sign(matrixfordeterminant.val) = -1 then 1 else 0 end) msign,
sum(case when matrixfordeterminant.val = 0 then 1 else 0 end) mzero
from matrixfordeterminant
inner join permutationselements
on matrixfordeterminant.nrow = permutationselements.rn
and matrixfordeterminant.ncol = permutationselements.el
inner join permutation_sign
on permutation_sign.path = permutationselements.path
group by matrixfordeterminant.rn, permutationselements.path, permutation_sign.psign
)
group by rn
)
select determinants.rn, determinants.det/(select determinants.det from determinants where rn = 0)
from determinants
where determinants.rn != 0
order by determinants.rn
Я думаю надо пробовать делать через CTE — оно больше для этого подходит.
Здравствуйте, umnik, Вы писали:
U>"Без использования процедурных расширений SQL. Один запрос SELECT"?
Ну да. Именно вот так. И пусть вас не смущает subquery factoring (with clause). Она нужна только лишь чтобы поименовать отдельные части запроса и сделать его более понятным. Избавиться от них можно просто механически подставив соответсвующие subquery вместо их имен во всем запросе.
В версии до 11gR2 оно ни на что большее не способно к сожалению.
В вот в MS Sql Server (CTE) или в Oracle 11gR2 (Recursive Subquery Factoring) оно уже может быть рекурсивным, что позволяет делать более интересные вещи. Хотя и они остаются в рамках "один запрос select", потому что они являются составной частью оператора select даже по стандарту ANSI.