Это самый краткий способ, которым я нашел, чтобы написать такие запросы в Access, которые требуют вытягивания всех столбцов, которые соответствуют первой строке в группе записей, которые упорядочены определенным образом.
Сначала я добавил UniqueID в вашу таблицу. В данном случае это просто поле AutoNumber. Возможно, у вас уже есть уникальное значение в вашей таблице, и в этом случае вы можете использовать это.
Сначала будет выбрана строка с источником 3, затем с источником 1, затем с источником 2. Если есть связь, выбирается строка с более высоким значением X1. Если есть дальнейшая связь, она нарушается значением UniqueID:
SELECT t.* INTO [Chosen Rows]
FROM TestTable AS t
WHERE t.UniqueID=
(SELECT TOP 1 [UniqueID] FROM [TestTable]
WHERE t.IYR=IYR ORDER BY Choose([Source],2,3,1), X1 DESC, UniqueID)
Это дает:
Unit IYR X1 Source UniqueID
A 2009 55 1 1
A 2010 150 3 4
A 2011 90 1 5
Я рекомендую (1) создать индекс для поля IYR - это значительно повысит вашу производительность для этого типа запроса, и (2) если у вас много (> ~ 100K) записей, это не так лучший выбор. Я считаю, что это работает довольно хорошо для таблиц в диапазоне 1-70К. Для больших наборов данных я хотел бы использовать мою функцию GroupIncrement для разбиения каждой группы (аналогично SQL Server ROW_NUMBER () OVER ).
Функция Choose()
является функцией VBA и может быть здесь неясной. В вашем случае это звучит так, как будто требуется некоторая интерактивность. Для этого вы можете создать вторую таблицу под названием «Выбор», например:
Rank Choice
1 3
2 1
3 2
Затем вы можете заменить следующее:
SELECT t.* INTO [Chosen Rows]
FROM TestTable AS t
WHERE t.UniqueID=(SELECT TOP 1 [UniqueID] FROM
[TestTable] t2 INNER JOIN [Choices] c
ON t2.Source=c.Choice
WHERE t.IYR=t2.IYR ORDER BY c.[Rank], t2.X1 DESC, t2.UniqueID);
Индексирование Source
для TestTable
и Choice
для таблицы Choices
может быть полезным и здесь, в зависимости от количества требуемых вариантов выбора.
Q:
Можете ли вы заставить это работать без необходимости использования суррогатного ключа? За
пример, что если уникальный ключ является составной
{Unit, IYR, X1, источник}
A:
Если у вас есть составной ключ, вы можете сделать это следующим образом - однако я думаю, что если у вас большой набор данных, это полностью убьет производительность запроса. Это может помочь проиндексировать все четыре столбца, но я не могу сказать наверняка, потому что я не использую этот метод регулярно.
SELECT t.* INTO [Chosen Rows]
FROM TestTable AS t
WHERE t.Unit & t.IYR & t.X1 & t.Source =
(SELECT TOP 1 Unit & IYR & X1 & Source FROM [TestTable]
WHERE t.IYR=IYR ORDER BY Choose([Source],2,3,1), X1 DESC, Unit, IYR)
В некоторых случаях вам может потребоваться объединить некоторые отдельные части ключа следующим образом (хотя Access обычно объединяет значения автоматически):
t.Unit & CStr(t.IYR) & CStr(t.X1) & CStr(t.Source)
Вы также можете использовать запрос в своих операторах FROM вместо фактической таблицы. Сам запрос создаст состав из четырех полей, используемых в ключе, и затем вы будете использовать новое имя ключа в предложении WHERE верхнего оператора SELECT и в SELECT TOP 1 [ключ] подзапроса.
В целом, я либо: (a) создаю новую таблицу с полем AutoNumber, (b) добавлю поле AutoNumber, (c) добавлю целое число и заполню его уникальным числом с помощью VBA - это полезно, когда вы получаете ошибку MaxLocks при попытке добавить AutoNumber или (d) использовать уже проиндексированный уникальный ключ.