Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Скачиваний:
49
Добавлен:
05.03.2016
Размер:
1.28 Mб
Скачать

7.5. Компонування даних у список

Часто при роботі з базами даних постає задача перетворення структур вихідних відносин для виконання ті або інші операції над ними. Однієї з таких задач є вибір даних із бази в список для наступної обробки.

У складі Турбо-Прологу для цих цілей передбачений стандартний предикат findall (знайти_усі). Даний предикат обчислює усі відповіді на запит і повертає їх у вигляді списку. Синтаксис цього предиката має вигляд:

findall( Variable, Predicat_expression, List_name) ,

де List_name – ім'я змінної списку відповідей на запит, Predicat_expression – запит з змінними, що записаний у вигляді деякого предикатного виразу; Variable – об’єкт предикатного виразу Predicat_expression, що визначає структуру елемента списку List_name.

Для пояснення використання даного предиката для перетворення структур даних в список розглянемо приклад (програма 7.7).

/* програма 7.7 */

domains

number, salary=integer

name=string

list_worker=name*

predicates

work(name, number, salary)

clauses

work(„Кардаш”, 101. 500).

work(„Денега”, 211,400 ).

work(„Петренко”, 101,300).

work(„Маслов”, 101,200).

Маємо базу даних work(), описану відповідним предикатом і задану набором фактів. Тому що обробка фактів здійснюється завжди в тому порядку, як вони задані в програмі, то можуть виникнути незручності, якщо потрібно буде сортувати, упорядковувати і т.п. прізвища співробітників.

Для цих цілей зручніше використовувати спискові структури організації даних.

Нехай для нашого приклада потрібно сформувати список прізвищ співробітників визначеного відділу.

Для цього потрібно описати структуру цього списку в секції domains і використовувати предикат findall у наступному виді:

findall( Name, work(Name, 101, _), List_Name),

Тут Name є вільною змінною для значень прізвищ, що задовольняють запитові у вигляді предикатного виразу work(Name, 101, _). Крім того, змінна Name визначає, що елементами списку List_Name будуть прізвища. У результаті виконання предикату findall список List_Name буде містити прізвища всіх службовців 101 відділу.

Завдання 6.

Для програми 7.7 виконайте зовнішній запит по формуванню списку співробітників заданого відділу. Задайте запит на формування списку окладів деякого відділу.

Приведений приклад показує, що предикат findall забезпечує фільтрацію, пошук і формування списку даних, що задовольняють умові пошуку в БД. Однак, даний приклад ілюстрував тільки сам процес пошуку і перетворення даних, не зв’язуючи його з процесом обробки.

Розглянемо ще один приклад, ілюструє той випадок, коли задача обробки даних визначає необхідність перетворення їх структур.

Нехай потрібно на основі бази даних work() знайти загальний фонд зарплати і середню зарплату в кожному з відділів. Програма 7.8 вирішує цю задачу.

/* програма 7.8 */

domains

number,salary=integer

name=string

list_salary=salary*

predicates

work(name,number,salary)

sum_list(list_salary,salary,integer)

show_sum

find_sum( number)

clauses

show_sum:-makewindow(1,7,15, "Зарплата:",5, 10, 12, 30), cursor(2,1), write("Введіть номер відділу -> "), readint(Otd), find_sum(Оtd), readchar(_).

find_sum(Оtd):- findall(Many, work(_, Otd, Many), Lmany), sum_list(Lmany, Sum, Member), write(“загальний фонд :”, Sum), nl, write(“службовців: ”, Member), nl, Ave=Sum/Member, write(“середня з/п: ”, Ave), nl.

sum_list([],0,0).

sum_list([H|T], Sum, Num):- sum_list(T, S, N), Sum=H+S, Num=N+1.

work(„Кардаш”, 101. 500).

work(„Денега”, 211,400 ).

work(„Петренко”, 101,300).

work(„Маслов”, 101,200).

Предикат show_sum дає можливість ввести номер потрібного відділу і забезпечити потрібний розрахунок, звернувшись до предиката find_sum().

Предикат find_sum() на основі фактів бази work() формує список окладів співробітників відділу – Lmany, обчислює суму елементів списку і їхню кількість, виводить отримані дані разом з обчисленим середнім значенням на екран.

Суму елементів списку знаходить предикат sum_list. Він же підраховує число елементів у списку.

У предикаті sum_list реалізована рекурсивна процедура, аналогічна тієї, що була використана при описі процедури пошуку довжини списку.

Завдання 7.

Доробіть програму 7.8 так, щоб до виводу підсумкових даних по відділу R виводився список усіх прізвищ для співробітників цього відділу.