Страницы

Поиск по вопросам

четверг, 15 ноября 2018 г.

Как быстро склеить зависимые записи в одну строку

Допустим, есть 2 таблицы:
1)Должность
2)Персонал, которая ссылается на Должность.
На одну запись Должность могут приходится несколько записей из Персонал.
Задача обновить [Весь персонал] в Должность склеенными в одну строчку зависимыми записями из Персонал.
Допустим приходится на 1 запись приходится 2 строчки ФИО из Персонал, мы их склеиваем и записываем в родительскую запись Должность.
Как это сделать быстро? Используется БД Access.
Сейчас я использую Interop, открываю RecordSet из Должность, и иду сверху вниз, и на каждую запись я открываю второй RecordSet из запроса 'Select PID,FIO From [Персонал] where PID='rst.fields[ID].value и иду сверху вниз и склеиваю значения, а потом возвращаю и обновляю их в первом RecordSet и мне кажется, что слишком это тормознуто и можно как то быстрее сделать это.
Наверное, через ADO.NET было бы быстрее, но мне кажется, что если БД Access будет здоровой, то слишком жирно все в память грузить разом...
UPD: Если все таки загрузить все в память и работать через ADO.NET, я получу значительный выигрыш в скорости?


Ответ

Можно написать VB функцию, которая будет склеивать строку. Подробно можно прочитать тут:
http://hiprog.com/index.php?option=com_content&task=view&id=334&Itemid=35
Тело функции:
Public Function UnionStr1(ID, Fam) Static IDOld, FamUnion If IDOld <> ID Then IDOld = ID FamUnion = Null End If
FamUnion = (FamUnion + ", ") & Fam UnionStr1 = FamUnion End Function
Пример запроса:
Select ID, Last(UnionStr1(ID,Fam)) AS FamUnion FROM Tab1 GROUP BY ID;
В той же статье есть интересный способ. Только средствами ms-access sql, с промежуточной таблицей. Хотя возможно в вашем случае её роль сыграет таблица Person(должностей). Выглядит примерно так:
Метод 3. Заполнение таблицы при помощи запросов (по Митину). http://c85.cemi.rssi.ru/Access/AnsPointDetail.idc?QID=14147
Оригинальный и неочевидный метод. Выполняется с помощью двух запросов. 1. Запись в Tab2 уникальных ID без фамилий. Текст запроса WriteID: INSERT INTO Tab2 (ID) Select DISTINCT ID FROM Tab1;
2. Запись списков фамилий. Текст запроса TabUnion5: UPDATE Tab2 INNER JOIN Tab1 On Tab2.ID = Tab1.ID Set Tab2.FamUnion = ([Tab2].[FamUnion]+", ") & [Tab1].[Fam];
Оценка скорости: по-видимому, работает быстрее метода 1 за счет отсутствия вызова специальных функций. Недостаток: "Однако в T-SQL это непрокатывает" (Митин).
Надо побаловаться, выглядит интересно.
UPD: Смысл в том, что из-за "глупости" ms-access SET будет выполнятся столько раз, сколько записей в присоединённой таблице(не той, которая апдейтится). Из-за "умности" T-SQL, в T-SQL этот способ работать не будет.
К минусам этого способа я бы ещё добавил потребность в сопровождении при переходе на новую версию access. Если MS решат приблизить хоть чуть-чуть ms-access к стандарту ANSI-SQL, этот метод может перестать работать.
С другой стороны, может они и для конкатенации строк что-нибудь сделают:) Хотя в этом вопросе даже MS SQL Server обделён вниманием до сих пор. MySQL, PostgreSQL, Oracle это давно умеют.

Комментариев нет:

Отправить комментарий