Добро пожаловать в форум, Guest  >>   Войти | Регистрация | Поиск | Правила | В избранное | Подписаться
Все форумы / Microsoft SQL Server Новый топик    Ответить
 Вычисление динамических формул. Аки калькулятор.  [new]
Awaiter
Member

Откуда:
Сообщений: 114
Привет.
Подскажите, сталкивался кто нибудь ?

Можно ли в MS SQL прикрутить "калькулятор"? Чтобы по формуле, представленной в виде строки, вычислялся результат.

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

UserIdParamName Value


и еще таблицу с формулами
FormulaId FormulaName StringFormula


Ну и таблицу с результатом расчитанной формулы
UserId FormulaId Result


Формулы простые, только стандартные операции *+-/

Собственно, осталось лишь найти SQL-Калькулятор. Знает кто-нибудь про такое ?
21 дек 14, 23:54    [17031332]     Ответить | Цитировать Сообщить модератору
 Re: Вычисление динамических формул. Аки калькулятор.  [new]
aleks2
Guest
А то.

declare @s nvarchar(1024)=N'2*2'

exec('select ' + @s);
22 дек 14, 06:24    [17031760]     Ответить | Цитировать Сообщить модератору
 Re: Вычисление динамических формул. Аки калькулятор.  [new]
a_voronin
Member

Откуда: Москва
Сообщений: 4804
Awaiter
Формулы простые, только стандартные операции *+-/


Вам нужно в запросе на лету или в скрипте? Решения могут быть разными.

Может вам не формулы, а шаблоны запросов с параметрами хранить?
22 дек 14, 13:23    [17033630]     Ответить | Цитировать Сообщить модератору
 Re: Вычисление динамических формул. Аки калькулятор.  [new]
ProBiotek
Member

Откуда: Moscow
Сообщений: 907
Awaiter это я. Это мой домашний логин :)

aleks2,
Не все так просто. У вас используются константы 2 и 2.... Все гораздо сложней, когда имеем формулу, ну там вида 'F/G*(2+SomeParam)'


a_voronin,
Я предполагаю, что удобней всего, если это реализовано в виде хранимой процедуры.
Не совсем Вас понял. Что значит "шаблоны запросов с параметрами хранить" ?

В целом, задача стоит так, что через админку нужно иметь возможность создавать-редактировать формулы. Предположим админ создал новую формулу: "2*(Ger/Fer)".

Для каждого пользователя будут забиты эти значения. Примерно так:
UserID ParamName Value
1 Ger 23.23
1 Fer 3.12


Есть ли готовое решение, которое распарсит формулу, и подставит под распознанные параметры их значения (из таблицы, или еще откуда-то) ?
22 дек 14, 15:53    [17035070]     Ответить | Цитировать Сообщить модератору
 Re: Вычисление динамических формул. Аки калькулятор.  [new]
Glory
Member

Откуда:
Сообщений: 104760
ProBiotek
Все гораздо сложней, когда имеем формулу, ну там вида 'F/G*(2+SomeParam)'

И чем это сложенее ?
22 дек 14, 15:57    [17035101]     Ответить | Цитировать Сообщить модератору
 Re: Вычисление динамических формул. Аки калькулятор.  [new]
Crimean
Member

Откуда:
Сообщений: 13148
CLR как вариант. но - не скульное это дело. ой, не скульное...
22 дек 14, 16:04    [17035147]     Ответить | Цитировать Сообщить модератору
 Re: Вычисление динамических формул. Аки калькулятор.  [new]
ProBiotek
Member

Откуда: Moscow
Сообщений: 907
Glory,
Ну собственно сложность в парсинге строки, вычислении там синтаксических токенов. Подстановка то уже просто, конечно. Но мне то нужен именно механизм парсинга строки, и распознавание формулы.
Если не распозналость, можно просто вернуть ошибку - чтобы админ перепроверил введенную формулу.


Crimean,

Написать CLR процедуру в MS SQL ?
Просто я как раз хотел бы избежать вынесение такой логики на машину пользователя. Мне кажется это работа БД все расчитывать. Глупо выносить кучу вычислений на клиентскую машину - это работа БД.
22 дек 14, 16:14    [17035223]     Ответить | Цитировать Сообщить модератору
 Re: Вычисление динамических формул. Аки калькулятор.  [new]
a_voronin
Member

Откуда: Москва
Сообщений: 4804
ProBiotek
ну там вида 'F/G*(2+SomeParam)'

a_voronin,
Я предполагаю, что удобней всего, если это реализовано в виде хранимой процедуры.
Не совсем Вас понял. Что значит "шаблоны запросов с параметрами хранить" ?


Я имел ввиду, может вам сохранять сразу
'SELECT F/G*(2+@SomeParam) FROM T'

и делать в вашей процедуре

EXEC @Query, @SomeParam

?
22 дек 14, 16:18    [17035253]     Ответить | Цитировать Сообщить модератору
 Re: Вычисление динамических формул. Аки калькулятор.  [new]
Glory
Member

Откуда:
Сообщений: 104760
ProBiotek
Ну собственно сложность в парсинге строки, вычислении там синтаксических токенов.

Разумеется конечную формулу без шаблона и списка параметров очень трудно будет распарсить

ProBiotek
Просто я как раз хотел бы избежать вынесение такой логики на машину пользователя. Мне кажется это работа БД все расчитывать.

А где у вас тут рассчеты то ?
Ваше "2*(Ger/Fer)" в TSQL будет выглядеть в лучшем случае как множество подзапросов в одно запросе.
А в худшем - как скрипт из отдельных запросов

ProBiotek
Глупо выносить кучу вычислений на клиентскую машину - это работа БД.

Вам парсинг предлагают вынести, а не вычисления.
22 дек 14, 16:19    [17035261]     Ответить | Цитировать Сообщить модератору
 Re: Вычисление динамических формул. Аки калькулятор.  [new]
aleks2
Guest
ProBiotek
Есть ли готовое решение, которое распарсит формулу, и подставит под распознанные параметры их значения (из таблицы, или еще откуда-то) ?


replace(...)
22 дек 14, 17:36    [17035873]     Ответить | Цитировать Сообщить модератору
 Re: Вычисление динамических формул. Аки калькулятор.  [new]
ProBiotek
Member

Откуда: Moscow
Сообщений: 907
Спасибо всем за ответы.
Задача не срочная, буду думать как лучше сделать.
22 дек 14, 17:39    [17035896]     Ответить | Цитировать Сообщить модератору
 Re: Вычисление динамических формул. Аки калькулятор.  [new]
iiyama
Member

Откуда:
Сообщений: 642
ProBiotek,
навскидку, уверен что можно написать оптимальней


declare @operators table (operator char(1))
declare @vars table(name varchar(10), value decimal(10,8))

insert  into @operators values('+'),('-'),('*'),('/'),('('),(')')
insert into @vars values('pi', 3.1415926),('R', 2)

declare @formula varchar(1000) set @formula='(2*pi*R+0.5)*cos(pi)*tan(pi/4)'

;with F as
(
select 
number,
SUBSTRING(@formula, number,1) chr 
from master..spt_values where type='P' AND number between 1 AND LEN(@formula)
), F1 AS
( 
select number, chr, CASE WHEN operator IS NULL THEN 0 ELSE 1 END is_oper
from F
	left join @operators O ON F.chr=O.operator 
), F2 as
(
select T1.*
from F1 T1
	LEFT JOIN F1 T2 ON T1.is_oper=T2.is_oper AND T1.number-1=T2.number
WHERE T2.number IS NULL

), F3 as
(
select T1.number, T1.is_oper, 
 SUBSTRING(@formula, T1.number,  ISNULL(oa.number, LEN(@formula)+1)-T1.number) as CONST
from F2 T1
	OUTER APPLY (select top 1 * from F2 T2 where T2.number>T1.number order by T2.number asc) oa
)
select  number, ISNULL(CAST(V.value AS VARCHAR(10)), F3.CONST) as Result
into #tmp
from F3
	LEFT JOIN @vars V ON F3.CONST=V.name AND  F3.is_oper =0

declare @sql varchar(1000)
select @sql = 'select '+
(select Result as 'data()' from #tmp for XML path(''))

--print @sql
exec (@sql)

drop table #tmp
22 дек 14, 17:58    [17036009]     Ответить | Цитировать Сообщить модератору
 Re: Вычисление динамических формул. Аки калькулятор.  [new]
aleks2
Guest
iiyama
ProBiotek,
навскидку, уверен что можно написать оптимальней

Естественно.
Достаточно использовать sp_executesql и имена переменныx в формате @p.
22 дек 14, 18:15    [17036119]     Ответить | Цитировать Сообщить модератору
Все форумы / Microsoft SQL Server Ответить