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

Откуда:
Сообщений: 145
Здравствуйте!
Есть таблица, хранящая формулу расчета в виде текста.
Эта формула зависит от неких параметров, которых может быть произвольное количество.
Например вычисление формулы (сам текст формулы это текст между select и from):
select CASE WHEN [Par1]=1
THEN
CASE WHEN ( [Par2] > 0 ) OR ([Par3] >0)
THEN [Par4]
else [Par1]
END
+
CASE WHEN [Par4]=1
THEN [Par2]
else [Par1]+10
END
else
30
END
from
(select 1 Par1, 2 Par2, 3 Par3, 4 Par4, 5 Par5) T

Сам запрос сильно упрощен для понимания.
Вопрос: Нужно узнать по какой ветке формулы пошло вычисление и ее выделить жирным, как показано ниже. Т.е в SQL мне нужно определить что выделять.

CASE WHEN [Par1]=1
THEN
CASE WHEN ( [Par2] > 0 ) OR ([Par3] >0)
THEN [Par4]

else [Par1]
END
+
CASE WHEN [Par4]=1
THEN [Par2]
else [Par1]+10
END
else
30
END
Примечание: в формуле могут использоваться только выражение case when then else end и логические и арифметические операции+ скобки. Все параметры всегда в квадратных скобках. Набор параметров для одной формулы всегда одинаков, но значения разные. И формул разных таких у меня более 1000 штук.

Подскажите как правильно "распарсить" формулу и найти "листья" дерева формулы?
21 мар 13, 11:15    [14076117]     Ответить | Цитировать Сообщить модератору
 Re: Как определить ветку(и), по которой прошел расчет?  [new]
Maxx
Member [скрыт]

Откуда:
Сообщений: 24290
У вас есть таблица в полях которой записан текст запроса ? Правильно ?
У вас есть некая ХП которая принимает в себя параметры и рожает динамический скл относительно парметров ?
Вы хотите понять куда оно попадет ?
И в конце концов ГДЕ НАДО ВЫДЕЛИТЬ текст ?
21 мар 13, 11:28    [14076216]     Ответить | Цитировать Сообщить модератору
 Re: Как определить ветку(и), по которой прошел расчет?  [new]
Mind
Member

Откуда: Лучший город на Земле
Сообщений: 2322
Mih_dim
Подскажите как правильно "распарсить" формулу и найти "листья" дерева формулы?

CASE (Transact-SQL)
How do I write a Parser in C#?
Parsing
22 мар 13, 00:37    [14079747]     Ответить | Цитировать Сообщить модератору
 Re: Как определить ветку(и), по которой прошел расчет?  [new]
Mih_dim
Member

Откуда:
Сообщений: 145
Maxx
У вас есть таблица в полях которой записан текст запроса ? Правильно ?
У вас есть некая ХП которая принимает в себя параметры и рожает динамический скл относительно парметров ?
Вы хотите понять куда оно попадет ?
И в конце концов ГДЕ НАДО ВЫДЕЛИТЬ текст ?


Извините что не отвечал - уезжал и инета не было.
У меня есть таблица где в определенном поле записаны тексты запросов. в каждой строке свой.
У вас есть некая ХП которая принимает в себя параметры и рожает динамический скл относительно парметров ? Да
Вы хотите понять куда оно попадет ? Да Надо знать в какую ветку запроса зайдет при тех или иных значениях входных параметров в этот набор кейсов.

А выделение ветки по которой прошло вычисление - это уже вторая задача и при решении первой уже не очень сложная.
Главное понять какие именно выражения в запросе дали такой результат.
25 мар 13, 12:05    [14091382]     Ответить | Цитировать Сообщить модератору
 Re: Как определить ветку(и), по которой прошел расчет?  [new]
Mih_dim
Member

Откуда:
Сообщений: 145
Mind
Mih_dim
Подскажите как правильно "распарсить" формулу и найти "листья" дерева формулы?

CASE (Transact-SQL)
How do I write a Parser in C#?
Parsing


Информацию об этом я и так знаю, тока мне нужно "распарсить" чисто в T-SQL. Я пытался написать, но что то очень уж сложно у меня выходит и все время находятся выражения которые не верно парсяться.

Может кто то уже "парсил" что нить подобное и есть более изящные решения??? Очень надо.
25 мар 13, 12:10    [14091409]     Ответить | Цитировать Сообщить модератору
 Re: Как определить ветку(и), по которой прошел расчет?  [new]
Mih_dim
Member

Откуда:
Сообщений: 145
Mind
Mih_dim
Подскажите как правильно "распарсить" формулу и найти "листья" дерева формулы?

CASE (Transact-SQL)
How do I write a Parser in C#?
Parsing


Информацию об этом я и так знаю, тока мне нужно "распарсить" чисто в T-SQL. Я пытался написать, но что то очень уж сложно у меня выходит и все время находятся выражения которые не верно парсяться.

Может кто то уже "парсил" что нить подобное и есть более изящные решения??? Очень надо.
25 мар 13, 12:13    [14091421]     Ответить | Цитировать Сообщить модератору
 Re: Как определить ветку(и), по которой прошел расчет?  [new]
Glory
Member

Откуда:
Сообщений: 104751
Mih_dim
Информацию об этом я и так знаю, тока мне нужно "распарсить" чисто в T-SQL.

Парсер работает с текстом. Парсер не может знать значений полей. Потому что значения эти будут известны только в момент выполнения.
25 мар 13, 12:18    [14091458]     Ответить | Цитировать Сообщить модератору
 Re: Как определить ветку(и), по которой прошел расчет?  [new]
Гость333
Member

Откуда:
Сообщений: 3683
Mih_dim
тока мне нужно "распарсить" чисто в T-SQL.
Может кто то уже "парсил" что нить подобное и есть более изящные решения???

Парсер T-SQL, написанный на T-SQL? Знатное извращение
Более изящное решение — парсить T-SQL не на T-SQL.
25 мар 13, 12:36    [14091592]     Ответить | Цитировать Сообщить модератору
 Re: Как определить ветку(и), по которой прошел расчет?  [new]
Mind
Member

Откуда: Лучший город на Земле
Сообщений: 2322
Гость333
Mih_dim
тока мне нужно "распарсить" чисто в T-SQL.
Может кто то уже "парсил" что нить подобное и есть более изящные решения???

Парсер T-SQL, написанный на T-SQL? Знатное извращение
А вы еще представьте себе "выделение жирным" на T-SQL. Картинка с другого сайта.

Mih_dim,
Для каждой задачи свой инструмент. Если уж очень надо - напишите CLR.
26 мар 13, 03:59    [14094944]     Ответить | Цитировать Сообщить модератору
 Re: Как определить ветку(и), по которой прошел расчет?  [new]
на самом деле не очень понял зад
Guest
Mih_dim,

как вариант можно все что после THEN и ELSE заменять на время поиска пути на последовательно наращиваемую битовую маску
и типо в какую-нибуь переменную (-ные) складывать. в конце получится общая или на каждый кейс своя битовая маска.

не получится если более ранний кейс меняет значения которые должны влиять на более поздний.
26 мар 13, 07:55    [14095036]     Ответить | Цитировать Сообщить модератору
 Re: Как определить ветку(и), по которой прошел расчет?  [new]
Гость333
Member

Откуда:
Сообщений: 3683
на самом деле не очень понял зад
не получится если более ранний кейс меняет значения которые должны влиять на более поздний.

Хм... а каким образом case может поменять какое-либо значение? Значения ведь меняются оператором присваивания?
26 мар 13, 11:35    [14095838]     Ответить | Цитировать Сообщить модератору
 Re: Как определить ветку(и), по которой прошел расчет?  [new]
Mih_dim
Member

Откуда:
Сообщений: 145
Гость333
Mih_dim
тока мне нужно "распарсить" чисто в T-SQL.
Может кто то уже "парсил" что нить подобное и есть более изящные решения???

Парсер T-SQL, написанный на T-SQL? Знатное извращение
Более изящное решение — парсить T-SQL не на T-SQL.


Я знаю только T-sql. И на другом написать не могу. Просто тупо перебором символов в цикле с проверкой последовательности их - этот вариант мне не нравиться и хотел спросить есть ли более изящный вариант (не в "лоб").
27 мар 13, 10:08    [14100161]     Ответить | Цитировать Сообщить модератору
 Re: Как определить ветку(и), по которой прошел расчет?  [new]
invm
Member

Откуда: Москва
Сообщений: 9915
Mih_dim,

Купите готовый. Предложений достаточно.
27 мар 13, 10:47    [14100392]     Ответить | Цитировать Сообщить модератору
 Re: Как определить ветку(и), по которой прошел расчет?  [new]
Mih_dim
Member

Откуда:
Сообщений: 145
Mind
Гость333
пропущено...

Парсер T-SQL, написанный на T-SQL? Знатное извращение
А вы еще представьте себе "выделение жирным" на T-SQL. Картинка с другого сайта.

Mih_dim,
Для каждой задачи свой инструмент. Если уж очень надо - напишите CLR.


Жирным выделить написал - это для понимания задачи. Если не знаете как решить на T-SQL, так не пишите. Я это так вижу: мне нужна хранимка в которую я буду передавать строку (формулу), а она мне будет возвращать таблицу.
Пример:
Строка: case when 1=2 then 2
else
case when 1=1 then 3 else 4 end + 45
end

Возвращается таблица:
IDNameflag
1case 0
2when 0
31=2 0
4then 0
52 0
6else 0
7case 0
8when 0
91=1 0
10then 0
113 1
13else 0
144 0
15end 0
16+ 1
1745 1
18end 0


Где flag=1 показывает, по каким "листьям" прошел расчет.
27 мар 13, 10:49    [14100408]     Ответить | Цитировать Сообщить модератору
 Re: Как определить ветку(и), по которой прошел расчет?  [new]
Glory
Member

Откуда:
Сообщений: 104751
Mih_dim
Если не знаете как решить на T-SQL, так не пишите.

Алгоритмов парсинга полно. Вы хоть один нашли ?
Или вы ищите готовый код на T-SQL ?
27 мар 13, 10:53    [14100433]     Ответить | Цитировать Сообщить модератору
 Re: Как определить ветку(и), по которой прошел расчет?  [new]
Mih_dim
Member

Откуда:
Сообщений: 145
invm
Mih_dim,

Купите готовый. Предложений достаточно.


Готовый на T-sql в виде хранимки? Вряд ли, а мне нужен именно такой.
27 мар 13, 11:03    [14100511]     Ответить | Цитировать Сообщить модератору
 Re: Как определить ветку(и), по которой прошел расчет?  [new]
Mih_dim
Member

Откуда:
Сообщений: 145
Glory
Mih_dim
Если не знаете как решить на T-SQL, так не пишите.

Алгоритмов парсинга полно. Вы хоть один нашли ?
Или вы ищите готовый код на T-SQL ?


Их много а какой применить к моей задачи не знаю.
Я ищю хотя бы подобный код чтобы его доработать или метод с помощью которого я бы написал сам.
1. Если есть уже подобное решение, то я бы посмотрел бы на него
2. Если нет, то подскажите какой лучше использовать алгоритм
3. Если не понятно какой лучше, то подскажите хотя бы какой проще для понимания.
27 мар 13, 11:07    [14100525]     Ответить | Цитировать Сообщить модератору
 Re: Как определить ветку(и), по которой прошел расчет?  [new]
Гость333
Member

Откуда:
Сообщений: 3683
Mih_dim
Просто тупо перебором символов в цикле с проверкой последовательности их - этот вариант мне не нравиться и хотел спросить есть ли более изящный вариант (не в "лоб").

1) Создаёте формальное описание грамматики подмножества языка T-SQL, которое используется в ваших выражениях. Это будет контекстно-свободная грамматика, более конкретно надо смотреть в процессе создания;
2) Пишете лексический анализатор, разбивающий исходный текст на литералы, используемые в грамматике;
3) Пишете синтаксический анализатор, строящий по набору литералов дерево разбора в соответствии с описанием грамматики;
4) Пишете семантический анализатор, который собственно уже сможет определить ветви дерева разбора, по которому пройдёт вычисление с указанными параметрами.
27 мар 13, 11:07    [14100526]     Ответить | Цитировать Сообщить модератору
 Re: Как определить ветку(и), по которой прошел расчет?  [new]
Glory
Member

Откуда:
Сообщений: 104751
Mih_dim
Их много а какой применить к моей задачи не знаю.

Вы предлагаете выбрать за вас ?
Mih_dim
Я ищю хотя бы подобный код чтобы его доработать или метод с помощью которого я бы написал сам.

То, что вы написали, есть обыкновенное разбиение строки на подстроки с разделителем пробел
27 мар 13, 11:10    [14100544]     Ответить | Цитировать Сообщить модератору
 Re: Как определить ветку(и), по которой прошел расчет?  [new]
Гость333
Member

Откуда:
Сообщений: 3683
Mih_dim
подскажите хотя бы какой проще для понимания.

Наверное, метод рекурсивного спуска. Хотя перспектива его реализации на T-SQL не очень ясна (из-за ограничения MSSQL — не более 32 вложенных вызовов хранимых процедур). Вот нашлась некая статья на Хабре с исходниками на Java (сперва я даже был в полной уверенности, что это C#): Парсер формул с помощью метода рекурсивного спуска.
27 мар 13, 11:33    [14100694]     Ответить | Цитировать Сообщить модератору
 Re: Как определить ветку(и), по которой прошел расчет?  [new]
Mih_dim
Member

Откуда:
Сообщений: 145
Glory
Mih_dim
Их много а какой применить к моей задачи не знаю.

Вы предлагаете выбрать за вас ?

Так зачем я пишу здесь по Вашему? Чтобы услышать совет людей, которые с этим работали.

Mih_dim
Я ищю хотя бы подобный код чтобы его доработать или метод с помощью которого я бы написал сам.

То, что вы написали, есть обыкновенное разбиение строки на подстроки с разделителем пробел


Да заполнение таблицы это не сложно, а вот проставление флага? Вот задача.
27 мар 13, 13:52    [14101689]     Ответить | Цитировать Сообщить модератору
 Re: Как определить ветку(и), по которой прошел расчет?  [new]
Mih_dim
Member

Откуда:
Сообщений: 145
Гость333
Mih_dim
подскажите хотя бы какой проще для понимания.

Наверное, метод рекурсивного спуска. Хотя перспектива его реализации на T-SQL не очень ясна (из-за ограничения MSSQL — не более 32 вложенных вызовов хранимых процедур). Вот нашлась некая статья на Хабре с исходниками на Java (сперва я даже был в полной уверенности, что это C#): Парсер формул с помощью метода рекурсивного спуска.


Спасибо я посмотрю этот метод.
27 мар 13, 13:53    [14101696]     Ответить | Цитировать Сообщить модератору
 Re: Как определить ветку(и), по которой прошел расчет?  [new]
Glory
Member

Откуда:
Сообщений: 104751
Mih_dim
Да заполнение таблицы это не сложно, а вот проставление флага? Вот задача.

Разумеется.
Для этого как указали в сообщении 14100526 нужно определять лексику, семантику, синтаксис. Грубо говоря, правила отличия подстроки "case" от подстроки "1=1"
27 мар 13, 13:56    [14101711]     Ответить | Цитировать Сообщить модератору
 Re: Как определить ветку(и), по которой прошел расчет?  [new]
Mih_dim
Member

Откуда:
Сообщений: 145
Glory
Mih_dim
Да заполнение таблицы это не сложно, а вот проставление флага? Вот задача.

Разумеется.
Для этого как указали в сообщении 14100526 нужно определять лексику, семантику, синтаксис. Грубо говоря, правила отличия подстроки "case" от подстроки "1=1"


Можно ссылку на любой пример этих 4 пунктов, а то в теории это слишком размыто. Лично я не могу в своей задаче разделить на эти 4 пункта?
27 мар 13, 15:14    [14102286]     Ответить | Цитировать Сообщить модератору
 Re: Как определить ветку(и), по которой прошел расчет?  [new]
Гость333
Member

Откуда:
Сообщений: 3683
Mih_dim,

Например, на http://kit.kulichki.net/ есть "методические материалы по курсу "Основы построения трансляторов".
27 мар 13, 16:06    [14102758]     Ответить | Цитировать Сообщить модератору
Все форумы / Microsoft SQL Server Ответить