Я хочу, чтобы работал следующий запрос, где [Tryme]
— это записанное правило, которое будет истинным или ложным, чтобы я мог проверить таблицу показателей контроля качества и получить таблицу всех, в данном случае, Employee
и проверить пары, которые нарушают мой правила.
SELECT
Temp.*, FunctionIWant([Temp.TryMe]) AS Checked
FROM
(SELECT
Employee.ID, Employee.[First Name], Employee.[Last Name],
Employee.Wage, Employee.Tenure,
TheseRules.ID, TheseRules.Check AS Tryme
FROM
Employee, TheRules AS TheseRules) AS Temp;
Ниже приведен оператор, который возвращает [Checked]
, возвращая логическое значение так, как я хочу. Текст, записанный для столбца Checked
, — это точный текст, который находится в Temp.Tryme
(чтобы быть более понятным, "1.05*[Tenure]+37>[Wage]"
— это строка).
SELECT
Temp.*, **1.05*[Tenure]+37>[Wage]** AS Checked
FROM
(SELECT
Employee.ID, Employee.[First Name], Employee.[Last Name], Employee.Wage,
Employee.Tenure, TheseRules.ID, TheseRules.Check AS Tryme
FROM
Employee, TheRules AS TheseRules) AS Temp;
Поскольку это просто другой уровень оценки, отличный от обычного, я надеюсь, что это возможно.
Я пробовал Eval()
, который возвращает либо саму строку, либо #Error
.
В настоящее время я пытаюсь создать функцию, которая бы это сделала, но не могу понять, как просто передать все поля функции, чтобы они могли быть оценены там.
Сейчас в нем 39 правил, но если бы это сработало, я бы увеличил это число, чтобы упростить задачу. Всего задействовано около 25 различных полей.
Поля берутся из разных таблиц, а выражения содержат разное количество полей? Да, это становится сложнее.
Чтобы функция Eval() работала, необходимо заменить строку [Tenure] значением поля Tenure (аналогично для Wage). Возможно, можно создать функцию, которая будет получать значения полей (включая строку выражения, хранящуюся в поле «Проверка») и выполнять соответствующие операции замены для создания строки выражения, которую может обработать Eval(). Я ожидаю, что это будет довольно сложно в зависимости от разнообразия оцениваемых «правил».
Функция может получать в качестве аргументов: имя таблицы данных, идентификатор записи, имя расчета, строку выражения. Откройте набор записей данной таблицы, отфильтрованный по идентификатору. Блок SELECT CASE будет определять имя вычисления и выполнять операции замены строки выражения, извлекая данные из полей набора записей.
Или отказаться от таблицы правил и использовать выражения жесткого кода функций. Перейдите к имени таблицы данных функции, идентификатору записи и имени расчета. По-прежнему используется SELECT CASE, но вместо операций замены строки выражения просто напрямую ссылаются на поля набора записей. Функция Eval() не требуется.
В любом из этих подходов по мере добавления «правил» процедура должна быть расширена для их соответствия. Чтобы избежать этого и упростить процедуру, можно использовать таблицу «сопоставления», в которой указаны имена полей и связанные строки в выражении, которое они заменяют. Вместо SELECT CASE откройте набор записей таблицы «сопоставления» и зациклите ее записи для выполнения соответствующих операций замены строкового выражения, после чего Eval() сможет обработать строку.
Пример таблицы сопоставления:
Функция:
Function CheckCalc(intI As Integer, strT As String, strE As String) As Boolean
Dim rsData As DAO.Recordset, rsMap As DAO.Recordset
Set rsData = CurrentDb.OpenRecordset("SELECT * FROM [" & strT & "] WHERE ID = " & intI)
Set rsMap = CurrentDb.OpenRecordset("SELECT * FROM ExpMap WHERE TblNme ='" & strT & "'")
Do While Not rsMap.EOF
strE = Replace(strE, rsMap!FldMask, rsData(rsMap!FldNme))
rsMap.MoveNext
Loop
CheckCalc = Eval(strE)
End Function
Предполагается, что каждая таблица имеет ключевое поле с именем ID. Если это не так, функцию придется изменить, чтобы передать это имя поля в качестве другого аргумента и построить оператор SQL с этой переменной. Маска в выражении может быть какой угодно, просто убедитесь, что все, что есть в выражении, находится в таблице сопоставления, например символы [ ], которые я удалил из выражения во время тестирования и поэтому не отображается в таблице сопоставления.
Если в выражении в качестве маски используется точное имя поля, можно исключить таблицу сопоставления и ее набор записей. Вместо этого процедура будет перебирать поля rsData и проверять с помощью InStr() его присутствие в строке выражения, и если оно есть, выполнять операцию замены.
Function CheckCalc(intI As Integer, strT As String, strE As String) As Boolean
Dim rsData As DAO.Recordset, fld As DAO.Field
Set rsData = CurrentDb.OpenRecordset("SELECT * FROM [" & strT & "] WHERE ID = " & intI)
For Each fld In rsData.Fields
If InStr(strE, fld.Name) Then
strE = Replace(strE, fld.Name, fld)
End If
Next
CheckCalc = Eval(strE)
End Function
Сколько «правил» вам нужно оценить? Сколько полей будет задействовано?