LEFT JOIN в MS-Access с несколькими критериями соответствия (И (ИЛИ)) - PullRequest
0 голосов
/ 03 марта 2020

Я работаю в MS-Access из Office 365.

t1 - это таблица с около 1000 строк. Я пытаюсь присоединиться к t1 с t2, где t2 чуть меньше 200 тыс. Строк. Я пытаюсь сопоставить строки, используя короткие текстовые строки в нескольких полях, и все соответствующие поля проиндексированы. Строки относительно короткие, с самыми длинными полями (полями улиц) в среднем около 15 символов.

Вот мой запрос:

SELECT one.ID, two.ACCOUNT
FROM split_lct_2 AS one LEFT JOIN split_parcel AS two 
ON (
nz(one.mySTREET) = nz(two.pSTREET)
OR nz(one.mySTREET_2) = nz(two.pSTREET)
OR nz(one.mySTREET_3) = nz(two.pSTREET)
) 
AND (nz(one.myDIR) = nz(two.pDIR)) 
AND (nz(one.myHOUSE) = nz(two.pHOUSE));

Запрос работает, однако он ведет себя как 3-летний Таблица запросов появляется через несколько секунд, но остается sluggi sh неопределенно долго. Например, выбор ячейки в наборе занимает 3-7 секунд. Экспорт таблицы запросов в формате .dbf занимает около 8 минут.

Меня беспокоит то, что это просто пример файла для построения запросов, фактический t1 будет иметь более 200 тыс. Строк для обработки.

Есть ли способ структурировать этот запрос, который значительно улучшит производительность?

Ответы [ 3 ]

0 голосов
/ 03 марта 2020

Определенно, объединение таблиц с использованием текстовых полей - это не то, на что вы надеетесь.

Но жизнь - это жизнь.

Если нет возможности преобразовать текстовые строки в целые числа (например, дополнительная таблица с названиями улиц и улиц), попробуйте это:

SELECT one.ID, two.ACCOUNT
FROM split_lct_2 AS one LEFT JOIN split_parcel AS two 
ON (nz(one.mySTREET) = nz(two.pSTREET)) 
AND (nz(one.myDIR) = nz(two.pDIR)) 
AND (nz(one.myHOUSE) = nz(two.pHOUSE))

UNION

SELECT one.ID, two.ACCOUNT
FROM split_lct_2 AS one LEFT JOIN split_parcel AS two 
ON (nz(one.mySTREET_2) = nz(two.pSTREET)) 
AND (nz(one.myDIR) = nz(two.pDIR)) 
AND (nz(one.myHOUSE) = nz(two.pHOUSE)

UNION

SELECT one.ID, two.ACCOUNT
FROM split_lct_2 AS one LEFT JOIN split_parcel AS two 
ON (nz(one.mySTREET_3) = nz(two.pSTREET)
) 
AND (nz(one.myDIR) = nz(two.pDIR)) 
AND (nz(one.myHOUSE) = nz(two.pHOUSE));
0 голосов
/ 03 марта 2020

Полагаю, использование Nz () не позволяет использовать индекс. Старайтесь избегать их. Если у данных нет пустых значений в полях ключей соединения, тогда Nz () следует безопасно удалить из запроса, и это должно помочь. Но если данные имеют значения NULL, вам, вероятно, нужно изменить это - например, заменить все NULL пустыми строками, чтобы сделать их совместимыми без Nz () - это дополнительная обработка данных вне этого запроса.

0 голосов
/ 03 марта 2020

Не знаю, поможет ли это, но

(
nz(one.mySTREET) = nz(two.pSTREET)
OR nz(one.mySTREET_2) = nz(two.pSTREET)
OR nz(one.mySTREET_3) = nz(two.pSTREET)
) 

совпадает с

nz(two.pSTREET) IN (nz(one.mySTREET),nz(one.mySTREET_2),nz(one.mySTREET_3))

, возможно, оптимизатор справится с этим лучше.

...