У меня есть запрос доступа, как показано ниже, и я хочу создать поля, выделенные желтым цветом
Описание:
Для ItemID есть группы и одна продолжительность, для каждой группы есть дни до и дни после.
Цель (3 условия):
1. Если элементы группы имеют полную продолжительность, т. е. флаг (Full_Dur) имеет значение «Да» для обоих, обязательные 2 поля (D_before_G и D_after_G) должны быть такими же, как D_before и D_after, как в группе «2».
2-Если один из элементов группы имеет полную продолжительность, а другой меньше, т. е. один флаг (Full_Dur) имеет значение «Да», а второй — «Нет», обязательные 2 поля (D_before_G и D_after_G) должны быть такими же, как D_before и D_after с флагом « Нет», как в группе «1» ItemID «2010».
3. Если элементы группы имеют меньшую продолжительность, т. е. флаг (Full_Dur) имеет значение «Нет» для обоих, обязательные 2 поля (D_before_G и D_after_G) должны совпадать с наименьшим D_before и наименьшим D_after.
Примечания:
Элементы группы состоят всего из двух чисел и не повторяются в «ItemID»
Поля D_before, D_after и Full_dur являются вычисляемыми полями запроса.
@ShahramAlemzadeh Я создал таблицу, и ее предварительный просмотр во время редактирования идеален, но после сохранения редактирования она не отображалась должным образом !!
Вычислить значение на основе данных в другой записи в Access непросто. См. пример на странице allenbrowne.com/subquery-01.html#AnotherRecord. Ваша ситуация имеет дополнительную сложность, поскольку необходимо получить несколько значений. Сначала необходимо проверить значение Full_dur в другой записи, чтобы определить, следует ли извлекать D_before_G и D_after_G из другой записи. Это настолько сложно, что может потребоваться специальная функция VBA. Если у вас есть код с проблемой, задайте вопрос.
Примеры данных для критерия 3 одинаковы для обеих записей. Возможно ли использование разных значений? Если да, то это будет лучший образец.
@June7 да, возможно для разных значений, данный образец (группа 3) заражен другим параметром «Доступность» (не показан) для этой группы, что означает, что эту группу нельзя использовать.
Единственный способ, который я мог придумать, - это использовать функции VBA. По одному на каждый столбец.
Откройте модуль в редакторе VBA и введите следующее:
Option Explicit
Public Function Get_D_before_G(iItemID As Long, iGroup As Integer)
Dim bFlag1 As Boolean, bFlag2 As Boolean
Dim iD_before1 As Integer, iD_before2 As Integer
With CurrentDb.OpenRecordset("SELECT Full_dur, D_before FROM qYourOriginalQuery WHERE ItemID = " & iItemID & " AND qYourOriginalQuery.Group = " & iGroup & ";", dbOpenDynaset)
.MoveFirst
bFlag1 = !Full_dur
iD_before1 = !D_before
.MoveNext
bFlag2 = !Full_dur
iD_before2 = !D_before
Select Case True
Case bFlag1 And bFlag2 'case 1: both are true
Get_D_before_G = !D_before
Case bFlag1 Or bFlag2 'case 2: this case excludes both are true, as this is the first case
If bFlag1 Then
Get_D_before_G = !D_before
Else
.MovePrevious
Get_D_before_G = !D_before
End If
Case Else 'case 3: both are false
If iD_before1 < iD_before2 Then
Get_D_before_G = iD_before1
Else
Get_D_before_G = iD_before2
End If
End Select
End With
End Function
Public Function Get_D_after_G(iItemID As Long, iGroup As Integer)
Dim bFlag1 As Boolean, bFlag2 As Boolean
Dim iD_after1 As Integer, iD_after2 As Integer
With CurrentDb.OpenRecordset("SELECT Full_dur, D_after FROM qYourOriginalQuery WHERE ItemID = " & iItemID & " AND qYourOriginalQuery.Group = " & iGroup & ";", dbOpenDynaset)
.MoveFirst
bFlag1 = !Full_dur
iD_after1 = !D_after
.MoveNext
bFlag2 = !Full_dur
iD_after2 = !D_after
Select Case True
Case bFlag1 And bFlag2 'case 1: both are true
Get_D_after_G = !D_after
Case bFlag1 Or bFlag2 'case 2: this case excludes both are true, as this is the first case
If bFlag1 Then
Get_D_after_G = !D_after
Else
.MovePrevious
Get_D_after_G = !D_after
End If
Case Else 'case 3: both are false
If iD_after1 < iD_after2 Then
Get_D_after_G = iD_after1
Else
Get_D_after_G = iD_after2
End If
End Select
End With
End Function
Затем добавьте к исходному запросу два новых столбца, например:
SELECT rest_of_your_columns, Get_D_before_G(ItemID, Group) AS D_before_G, Get_D_after_G(ItemID, Group) AS D_after_G
FROM rest_of_your_query;
Важные замечания об этом методе:
qYourOriginalQuery
в функциях (есть 4 раза) на тот, который у вас уже есть.ItemID
и Group
должен быть числовым. Если нет, то операторы SELECT
в функциях VBA необходимо изменить.ItemID
и Group
существуют только парами, как вы утверждаете. То есть их каждый раз строго 2. Если их больше или меньше, то этот метод не сработает.Group
, поскольку это зарезервированное слово и может вызвать у вас проблемы.Он работает отлично, спасибо, Минтс. Я только тестирую его и рассмотрю его детали.
Вы можете решить это с помощью двух запросов.
Первый запрос — это запрос GROUP BY, который находит наименьшее значение для поля Full_dur. Т.е. если есть запись «Нет», она вернет «Нет», в противном случае она вернет «Да» в качестве поля YesOrNo.
Во втором запросе вы создаете два Dlockup() для значений в D_before и D_after с фильтрацией по идентификатору, ItemID, группе и полю YesOrNo из первого запроса.
Имя основного запроса в этом примере — qryData.
Первый запрос (qryDataFindNo) выглядит так:
Второй запрос выглядит следующим образом:
Поиски:
D_before_G: DLookUp("D_before","qryData","ID = " & [qryData].[ID] & " AND ItemID = " & [qryData].[ItemID] & " AND Group = " & [qrydata].[Group] & " AND Full_dur = """ & [YesOrNo] & """")
D_after_G: DLookUp("D_after","qryData","ID = " & [qryData].[ID] & " AND ItemID = " & [qryData].[ItemID] & " AND Group = " & [qrydata].[Group] & " AND Full_dur = """ & [YesOrNo] & """")
Спасибо, Мик, я попробовал ваше решение, но результат для ItemID = 2010 и группы 1 неверен (он должен быть 15 и 19 для обеих записей, но результат для обеих равен 65,0).
Тогда ваше поле Full_dur может иметь логическое значение Yes=-1 и No=0, поэтому функция Min в первом запросе возвращает строку Yes. Решение: Измените функцию Min- на Max в первом запросе.
И еще хорошо бы убрать кавычки в двух DLookUps. . AND Full_dur = """ & [ДаИлиНет] & """" на AND Full_dur = " & [Да Нет]
Вы правы, после изменения Min на Max все работает нормально.
Пожалуйста, вставьте таблицу данных и результаты в виде форматированного текста. См. Таблицу для помощи.