Запрос доступа: сравните записи в группе, а затем выберите одну на основе критерия в другом поле

У меня есть запрос доступа, как показано ниже, и я хочу создать поля, выделенные желтым цветом
Описание:
Для 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 являются вычисляемыми полями запроса.

ИДЕНТИФИКАТОР Идентификатор предмета Группа Продолжительность D_before Д_после Полная_длительность D_before_G D_after_G 1 2010 год 1 65 65 0 Да 15 19 1 2010 год 1 65 15 19 Нет 15 19 1 2010 год 2 65 65 0 Да 65 0 1 2010 год 2 65 65 0 Да 65 0 1 2010 год 3 65 0 0 Нет 0 0 1 2010 год 3 65 0 0 Нет 0 0 2 1040 1 100 100 0 Да 100 0 2 1040 1 100 100 0 Да 100 0

Пожалуйста, вставьте таблицу данных и результаты в виде форматированного текста. См. Таблицу для помощи.

Shahram Alemzadeh 19.05.2024 13:21

@ShahramAlemzadeh Я создал таблицу, и ее предварительный просмотр во время редактирования идеален, но после сохранения редактирования она не отображалась должным образом !!

Ashraf Fouad 19.05.2024 14:20

Вычислить значение на основе данных в другой записи в Access непросто. См. пример на странице allenbrowne.com/subquery-01.html#AnotherRecord. Ваша ситуация имеет дополнительную сложность, поскольку необходимо получить несколько значений. Сначала необходимо проверить значение Full_dur в другой записи, чтобы определить, следует ли извлекать D_before_G и D_after_G из другой записи. Это настолько сложно, что может потребоваться специальная функция VBA. Если у вас есть код с проблемой, задайте вопрос.

June7 19.05.2024 20:41

Примеры данных для критерия 3 одинаковы для обеих записей. Возможно ли использование разных значений? Если да, то это будет лучший образец.

June7 19.05.2024 20:54

@June7 да, возможно для разных значений, данный образец (группа 3) заражен другим параметром «Доступность» (не показан) для этой группы, что означает, что эту группу нельзя использовать.

Ashraf Fouad 20.05.2024 07:08
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
0
5
63
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Единственный способ, который я мог придумать, - это использовать функции 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, поскольку это зарезервированное слово и может вызвать у вас проблемы.

Он работает отлично, спасибо, Минтс. Я только тестирую его и рассмотрю его детали.

Ashraf Fouad 20.05.2024 09:05
Ответ принят как подходящий

Вы можете решить это с помощью двух запросов.

Первый запрос — это запрос 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).

Ashraf Fouad 20.05.2024 08:53

Тогда ваше поле Full_dur может иметь логическое значение Yes=-1 и No=0, поэтому функция Min в первом запросе возвращает строку Yes. Решение: Измените функцию Min- на Max в первом запросе.

Micke 21.05.2024 01:26

И еще хорошо бы убрать кавычки в двух DLookUps. . AND Full_dur = """ & [ДаИлиНет] & """" на AND Full_dur = " & [Да Нет]

Micke 21.05.2024 01:30

Вы правы, после изменения Min на Max все работает нормально.

Ashraf Fouad 23.05.2024 12:20

Другие вопросы по теме