Логические языки запросов



жүктеу 53.79 Kb.
Дата27.03.2018
өлшемі53.79 Kb.
түріЛекция

Подзапросы.



Пример.
Найти производителей сортов пива, продаваемых Joe.
SELECT DISTINCT b.manf

FROM ( SELECT s.beer

FROM Sells s

WHERE s.bar.name = "Joe's Bar"

) b
Кванторы.

FOR ALL x IN <коллекция> : <условие>

EXISTS x IN < коллекция > : < условие >


  • Выражение имеет значение TRUE если условие истинно для всех (или соответственно для, по крайней мере, одного) элементов коллекции.


Пример.
Найти все бары, продающие какое-либо пиво дороже $5.
SELECT b.name

FROM Bars b

WHERE EXISTS s IN b.beersSold : s.price > 5.00
Проблема.
Как найти бары, продающие пиво только дороже $5?
Пример.
Найти такие бары, которые продают дороже $5 только сорта пива производимые Питом (Pete's).
SELECT b.name

FROM Bars b

WHERE FOR ALL be IN

(

SELECT s.beer



FROM b.beersSold s

WHERE s.price > 5.00

) : be.manf = "Pete's"

Извлечение элементов коллекции.


  1. Коллекция с единственным элементом: извлечение при помощи оператора ELEMENT.


Пример.
Найти цену Bud в баре Joe и поместить результат в переменную p.
p = ELEMENT(

SELECT s.price

FROM Sells s

WHERE s.bar.name = "Joe's Bar"

AND s.beer.name = "Bud"

)


  1. Извлечение элементов коллекции по одному:

1. Преобразовать коллекцию в список.

2. Извлечь элемент списка при помощи <имя_списка>[i].

Пример.
Вывести меню Joe в порядке возрастания цен, пиво с одинаковой ценой расположить по алфавиту.
L = SELECT s.beer.name, s.price

FROM Sells s

WHERE s.bar.name = "Joe's Bar"

ORDER BY s.price, s.beer.name;


printf("Beer\tPrice\n\n");

for(i=1; i<=COUNT(L); i++)

printf("%s\t%f\n",L[i].name, L[i].price);

Агрегирование.
Пять операторов агрегирования avg, min, max, sum, count применяются к любой коллекции, если операторы имеют смысл для этого типа элементов.
Пример.
Найти среднюю цену пива у Joe.
x = AVG( SELECT s.price

FROM Sells s

WHERE s.bar.name = "Joe's Bar"

);


  • Замечание: хотя результат SELECT технически является набором структур, для одноэлементных структур, он заменяется набором значений этого элемента.

Группирование.
Напомним группирование в SQL, например:
SELECT bar, AVG(price)

FROM Sells

GROUP BY bar;


  • Является ли значение bar именем группы или общим значением атрибута bar для всех кортежей группы?

  • В SQL это не имеет значения, но в OQL можно создавать группы по значениям любой функции, а не только по значению атрибута.

  • Таким образом, группы определяются общим значением, а не именем.

  • Например, группы по первой букве названия бара (для этого необходим соответствующий метод).



Набросок работы группирования в OQL.

Коллекция,

определенная

FROM, WHERE


группирование

по значению(ям)

функции


Коллекция по


значениям функции

и разделам




Термы из


SELECT

Коллекция вывода


Пример. Найти среднюю цену пива в каждом баре.
SELECT barName,

avgPrice: AVG( SELECT p.s.price

FROM partition p

)

FROM Sells s



GROUP BY barName: s.bar.name


  1. Начальная коллекция Sells.




  • Технически – это набор структур вида Struct(s: s1), где s1 является объектом Sell. Заметьте, что объект переименован в s; в общем случае имеются имена для всех «типичных объектов» в части FROM .




  1. Промежуточная коллекция:




  • Одна функция: s.bar.name ставит в соответствие объекту Sell значение имени бара, на который ссылается s.




  • Коллекция является множеством структур вида:

Struct{

barName: string,

partition: Set

}

Например:



Struct(barName = "Joe's Bar", partition = {s1, …, sn})

где s1, …, sn являются одноэлементными структурами с именем s, значениями которых является один из объектов Sell, представляющий продажу некоторого пива в баре Joe.




  1. Коллекция вывода: состоит из пар пиво-средняя цена, по одной паре для каждой структуры из промежуточной коллекции.

  1. Тип структур при выводе:

Struct{barName: string, avgPrice: real}

  1. Заметьте, что в подзапросе SELECT:

SELECT barName,

avgPrice: AVG(

SELECT p.s.price

FROM partition p

)

p пробегает множество всех структур в разделе(partition). Каждая из этих структур имеет единственный элемент с именем s и имеет объект Sell в качестве значения. Так, p.s.price извлекает цену из одного из объектов Sell.


  1. Типичная структура вывода:

Struct(barName = "Joe's Bar", avgPrice = 2.83)

Другой, менее типичный пример.
Посчитать для каждого пива число баров, которые берут «низкую»(< 2.00) и высокую (> 4.00) цену за это пиво.
Группируем по трем величинам:

  • Название пива,

    • Булевская функция, возвращающая TRUE для низкой цены.

    • Булевская функция, возвращающая TRUE для высокой цены.

SELECT beerName, low, high, count: COUNT(partition)

FROM Beers b, b.soldBy s

GROUP BY beerName: b.name,

low: s.price <= 2.00,

high: s.price >= 4.00




  1. Начальная коллекция: пары (b; s), где b является объектом Beer, s является объектом Sell, представляющим продажу этого пива в некотором баре.




    • Тип элементов коллекции:

Struct{b: Beer, s: Sell}


  1. Промежуточная коллекция: четверки, состоящие из названия пива, булевских значений, говорящих, что эта группа соответствует «низкой»(1,0), «высокой»(0,1) или промежуточной(0,0) цене за это пиво, и раздел для данной группы.

  • Раздел является множеством структур вида:

Struct{b: Beer, s: Sell}
Типичное значение:

Struct(b: объект Bud, s: объект Sell включающий Bud)




  • Тип четверок в промежуточной коллекции:

Struct{ beerName: string,

low: boolean,

high: boolean,

partition: Set

}
Типичные значения в промежуточной коллекции:
beerName low high partition


Bud TRUE FALSE Slow

Bud FALSE TRUE Shigh

Bud FALSE FALSE Smid

... ... ... ...
где Slow Shigh, и Smid являются множествами пар пиво-продажа (b; s), с пивом Bud и s имеет, соответственно, «низкую» (< 2.00), «высокую» (> 4.00) и промежуточную (между 2.00 и 4.00) цену.


  • Замечание: раздел с low = high = TRUE должен быть пустым, и потому – отсутствовать.


  1. Коллекция вывода: первых три компоненты структуры группы копируются в коллекцию вывода, для последней (partition) – подсчитывается количество элементов в разделе.

Результат:




beerName low high count




Bud TRUE FALSE 27

Bud FALSE TRUE 14

Bud FALSE FALSE 36



... ... ... ...

Достарыңызбен бөлісу:


©kzref.org 2017
әкімшілігінің қараңыз

    Басты бет