Создание запросов

В AnyLogic, вы обычно создаете запросы на выборку, используя удобный графический конструктов запросов.

Однако вы можете создавать и специализированные запросы, используя один из двух альтернативных синтаксисов: Java SQL, или Query DSL.

Java SQL

Вы можете написать запрос, используя обычный SQL. Чтобы выполнить SQL утверждение, используйте функцию AnyLogic selectUniqueValue() или selectFirstValue(). Обе функции содержат два аргумента: возвращаемое значение и текстовый SQL запрос (типа String).

selectUniqueValue() возвращает единственное значение, а если будет несколько значений, удовлетворяющих выбранному условию, вы увидите сообщение об ошибке.

selectFirstValue() не выдаст ошибку в случае нескольких допустимых значений, просто вернет первое значение из результата запроса.

Пример:

selectUniqueValue(double.class, "SELECT processing_time FROM processing_times WHERE part = agent.name;");

Как мы видим, используется обычный SQL запрос. Однако, обращаем ваше внимание, разбив запрос на несколько строк (как показано ниже) вы получите ошибку.

selectUniqueValue(double.class, "SELECT processing_time
FROM processing_times WHERE part = agent.name;");

Чтобы продолжить писать запрос с новой строки, следует закончить текущую строку пробелом, поставить кавычки ", затем поставить символ сложения , и после этого начать новую строку символом ". То есть, допустимый многострочный запрос в AnyLogic должен выглядеть следующим образом:

selectUniqueValue(double.class, "SELECT processing_time "
"FROM processing_times WHERE part = agent.name;");

QueryDSL. Каскадный стиль синтаксиса

В Query DSL, вызовите функцию selectFrom() и используйте каскадные функции интерфейса SQLQuery: where, groupBy, having, orderBy, join, и т.д.

Пример:

(double)selectFrom( courses ).
where( courses.course.eq( courseName ) ).
uniqueResult( courses.duration_days )

Если нужен дополнительный оператор в запрос на выборку, необходимо поставить точку и поместить вызов соответствующей каскадной функции наподобие нашей, где where() определяет предмет выборки, а uniqueResult() позволяет возвращать единственный результат, а не несколько допустимых.

Чтобы писать запросы в Query DSL, ознакомьтесь со статьей с примерами использования оператора SELECT.

Также есть отдельные статьи о следующих SQL операторах и их аналогах в Query DSL: ORDER BY, GROUP BY, WHERE, INSERT, UPDATE, DELETE.

Ниже краткое описание каскадных функций:

innerJoin, join, leftJoin, fullJoin, on : Используйте эти операторы, чтобы определить элементы объединения. Для функции JOIN первый аргумент является источником сложения, а второй целью (псевдонимом).

where : Определяет фильтры запроса либо в функции с переменным количеством аргументов (varargs) с разделением запятыми, либо каскадно через оператор and.

groupBy : Определяет аргументы оператора группировки group by в функции с переменным количеством аргументов.

having : HAVING аналогичен WHERE за исключением того, что строки отбираются не по значениям столбцов, а строятся из значений столбцов, указанных в GROUP BY, и значений агрегатных функций, вычисленных для каждой группы, образованной GROUP BY.

orderBy : Используйте orderBy для сортировки данных, возвращаемых запросом.

limit, offset, restrict : Определяет вывод результата. Выражение LIMIT может использоваться для ограничения количества строк, возвращенных командой SELECT. Оператор Offset позволяет пропустить указанное количество строк перед тем как выводить результаты запроса.

list : Определяет перечень значений для столбцов таблицы, которые указаны как аргументы функции.

all : Выводит значения всех столбцов опрашиваемой таблицы БД

uniqueResult : Возвращает единственный результат.

firstResult : Возвращает первый результат по определенному запросу на выборку, или null если ничего не найдено

Сортировка (ORDER BY)

Вы можете отсортировать результаты запроса выборки SELECT в порядке возрастания или убывания значений в определенном столбце (или поочередно в нескольких столбцах) при помощи SQL оператора ORDER BY.

Вам необходимо указать названия столбца (или столбцов), по которым будет производиться сортировка. Для каждого столбца вы указываете порядок сортировки записей, добавляя ASC, если вы будете сортировать записи по возрастанию, или DESC - в случае сортировки по убыванию. В SQL, если иное не указано, по умолчанию применяется сортировка по возрастанию.

В данном примере мы осуществляем выборку из базы данных сотрудников employees. Нам нужно отобразить имя сотрудника, его оклад и возраст. Мы сортируем записи по имени (в порядке возрастания), а затем по окладу (в порядке убывания).

SELECT e.name, e.salary, e.age
FROM employees e
ORDER BY e.name ASC, c.salary DESC;

Так этот запрос выглядит в QueryDSL:

selectFrom(employees)
.orderBy(employees.name.asc(), employees.salary.desc())
.list(employees.name, employees.salary, employees.age);

В QueryDSL, вы указываете порядок сортировки, вызывая сортировщик asc() или desc() для каждого столбца в списке сортировки orderBy().

Группировка (GROUP BY)

Вы можете группировать результаты запроса SELECT на основе одного или нескольких столбцов, используя SQL оператор GROUP BY. После оператора GROUP BY нужно указать имя столбца, который, возможно, содержит повторяющиеся имена. Выполнив группировку, у вас будет только одна запись для каждого значения указанного в столбце. Как правило, вы можете использовать определенные агрегирующие функции SQL, чтобы отобразить в других столбцах сумму, максимум, минимум или количество сгруппированных записей.

В утверждении SELECT выражение GROUP BY следует за условием WHERE и предшествует выражению ORDER BY.

Предположим, у нас есть таблица awards победителей по версии FIFA Golden Ball и мы хотим посчитать количество наград у каждого игрока:

year player
2010 Lionel Messi
2011 Lionel Messi
2012 Lionel Messi
2013 Cristiano Ronaldo
2014 Cristiano Ronaldo

Мы хотим посчитать количество наград для каждого игрока и с этой целью будем использовать группировку. В SQL группировку можно выполнить следующим образом:

SELECT player, COUNT(player) FROM awards GROUP BY player;

это эквивалентно следующему запросу QueryDSL:

selectFrom(awards) .groupBy(awards.player)
.list(awards.player, awards.player.count());

Получим результат:

Lionel Messi 3
Cristiano Ronaldo 2

Условие WHERE

Оператор WHERE используется в выражениях запросов вставки, обновления и удаления SELECT, UPDATE и DELETE. С его помощью вы можете задать условие выбора определенных записей для их последующего отбора / обновления / удаления.

Вы задаете условие с помощью следующих операторов сравнения:

Операция сравнения

SQL оператор

QueryDSL оператор

Равно

=

eq()

Не равно

NOT

ne()

Больше, чем

>

gt()

Больше или равно

>=

goe()

Меньше, чем

<

lt()

Меньше или равно

<=

loe()

Использование оператора WHERE в запросе выборки SELECT

В следующем примере мы осуществляем выборку из таблицы factories тех предприятий, прибыль которых составляет более 100000 у.е.:

SQL

SELECT name, country, profit FROM factories f WHERE f.profit > 100000;

QueryDSL

selectFrom(factories)
.where(factories.profit.goe(100000))
.list(factories.number, factories.country, factories.profit);

Задание сложных условий

Вы можете задавать сложные условия, комбинируя несколько условий с помощью операторов AND и OR.

В следующем примере мы добавили еще одно условие. Мы осуществляем выборку прибыльных предприятий, расположенных во Франции:

SQL

SELECT name, country, profit FROM factories f WHERE f.profit > 100000 AND country = 'France';

QueryDSL

selectFrom(factories)
.where(factories.profit.goe(100000).and(factories.country.eq("France")))
.list(factories.number, factories.country, factories.profit);

Вы можете формировать сложные условия путем комбинирования операторов AND и OR. Чтобы комбинировать несколько операторов, используйте скобки. В следующем примере отражено применение обоих операторов AND и OR. Здесь мы осуществляем выборку всех прибыльных предприятий в Нидерландах, Бельгии и Люксембурге.

Необходимо выбрать данные из всех колонок таблицы. Для этого мы применяем SELECT * в SQL, и list() в QueryDSL.

SQL

SELECT * FROM factories f WHERE f.profit > 100000 AND (country = 'Netherlands' OR country = 'Belgium' OR country = 'Luxembourg');

QueryDSL

selectFrom(factories)
.where(
factories.profit.goe(100000).and(factories.country.eq("Netherlands").or(factories.country.eq("Belgium")).or(factories.country.eq("Luxembourg")))
.list();

Аналогично вы можете использовать оператор WHERE и в запросах UPDATE и DELETE.

Вставка (INSERT)

Добавлять новые записи в таблицу базы данных можно с помощью SQL запроса вставки INSERT INTO.

Ниже приведен пример запроса с использованием альтернативных синтаксисов, поддерживаемых AnyLogic:

SQL

executeStatement("INSERT INTO eu (country, capital) VALUES ('Croatia', 'Zagreb')");

QueryDSL

insertInto(eu)
.columns(eu.country, eu.capital)
.values("Croatia", "Zagreb")
.execute();

Запрос (UPDATE)

Запрос SQL UPDATE используется для редактирования существующих записей в таблице БД.

Представим, что мы меняем имя определенного человека в нашей БД actors.

Синтаксис UPDATE в SQL выглядит следующим образом:

executeStatement("UPDATE actors SET name = 'Kaley Cuoco -Sweeting' WHERE name = 'Kaley Cuoco'");

В данном случае мы выделяем определенные записи с помощью оператора WHERE и устанавливаем новое значение 'Kaley Cuoco -Sweeting' в столбце name для всех полученных записей. В операторе WHERE, можно сочетать несколько условий, используя операторы AND и OR.

Эквивалент функции в QueryDSL:

update(actors)
.where(actors.name.eq(
"Kaley Cuoco"))
.set(actors.name, "Kaley Cuoco-Sweeting")
.execute();

Как редактировать несколько значений

Прошлый пример был простым. Сейчас рассмотрим как редактировать несколько значений сразу.

Предположим мы хотим также отредактировать семейное положение. Решение очевидно, если данные представлены в виде строковой функции String, поэтому сейчас мы рассмотрим возможность отредактировать значение, которое представлено в виде элемента списка вариантов. Предположим, что статус в модели представлен в виде списка вариантов MaritalStatus с элементами (SINGLE, MARRIED).

Запросы должны выглядеть:

update(actors)
.where(actors.name.eq(
"Kaley Cuoco"))
.set(actors.name, "Kaley Cuoco-Sweeting")
.set(actors.status, MARRIED)
.execute();

executeStatement("UPDATE actors SET name = ?, status = ? WHERE name = ?",
"Kaley Cuoco-Sweeting", MARRIED, "Kaley Cuoco");

Удаление (DELETE)

С помощью запроса SQL DELETE производится удаление существующих записей из таблицы базы данных.

Указать, какие именно записи нужно удалить, можно задав соответствующее условие с помощью оператора WHERE. Вы можете задавать сложные условия, объединяя несколько простых условий с помощью операторов AND и/или OR. Более подробную информацию об операторе WHERE и составлении сложных условий вы можете найти здесь.

Пример запроса удаления:

SQL

executeStatement("DELETE FROM employees e WHERE e.age >= 60 AND e.gender = 'male'");

QueryDSL

deleteFrom(employees)
.where(employees.age.goe(60).and(employees.gender.eq("male")))
.execute();

Удаление всех записей из таблицы БД:

Чтобы удалить все записи из таблицы, не добавляйте никаких условий:

SQL

executeStatement("DELETE FROM customers c");

QueryDSL

deleteFrom(customers)
.execute();