Шпаргалка по основам SQL
Основы SQL
Найти все столбцы и строки в таблице / Find All Columns and Rows in a Table
SELECT * FROM <table name>;
Символ звездочки или астериск (*
) означает все столбцы.
точка с запятой (;
) завершает утверждение как точка в предложении или вопросительный знак в вопросе.
Пример:
SELECT * FROM books;
SELECT * FROM products;
SELECT * FROM users;
SELECT * FROM countries;
Получение определенных столбцов информации / Retrieving Specific Columns of Information
Получение одного столбца:
SELECT <column name> FROM <table name>;
Пример:
SELECT email FROM users;
SELECT first_name FROM users;
SELECT name FROM products;
SELECT zip_code FROM addresses;
Получение нескольких столбцов:
SELECT <column name 1>, <column name 2>, … FROM <table name>;
Пример:
SELECT first_name, last_name FROM customers;
SELECT name, description, price FROM products;
SELECT title, author, isbn, year_released FROM books;
SELECT name, species, legs FROM pets;
Псевдонимы имен столбцов / Aliasing Column Names
SELECT <column name> AS <alias> FROM <table name>;
SELECT <column name> <alias> FROM <table name>;
Пример:
SELECT username AS Username, first_name AS "First Name" FROM users;
SELECT title AS Title, year AS "Year Released" FROM movies;
SELECT name AS Name, description AS Description, price AS "Current Price" FROM products;
SELECT name Name, description Description, price "Current Price" FROM products;
Поиск нужных данных / Finding the Data You Want
SELECT <columns> FROM <table> WHERE <condition>;
Оператор равенства / Equality Operator
Найти все строки, в которых заданное значение соответствует значению столбца.
SELECT <columns> FROM <table> WHERE <column name> = <value>;
Пример:
SELECT * FROM contacts WHERE first_name = "Andrew";
SELECT first_name, email FROM users WHERE last_name = "Chalkley";
SELECT name AS "Product Name" FROM products WHERE stock_count = 0;
SELECT title "Book Title" FROM books WHERE year_published = 1999;
Оператор неравенства / Inequality Operator
Найти все строки, в которых заданное значение не соответствует значению столбца.
SELECT <columns> FROM <table> WHERE <column name> != <value>;
SELECT <columns> FROM <table> WHERE <column name> <> <value>;
Оператор не равно или неравенства можно записать двумя способами. !=
и <>
. Последнее less общий.
Пример:
SELECT * FROM contacts WHERE first_name != "Kenneth";
SELECT first_name, email FROM users WHERE last_name != "L:one";
SELECT name AS "Product Name" FROM products WHERE stock_count != 0;
SELECT title "Book Title" FROM books WHERE year_published != 2015;
Реляционные операторы / Relational Operators
Вы можете использовать несколько реляционных операторов:
<
less than<=
less than or equal to>
greater than>=
greater than or equal to
Они в основном используются для сравнения numeric а также date/time типов.
SELECT <columns> FROM <table> WHERE <column name> < <value>;
SELECT <columns> FROM <table> WHERE <column name> <= <value>;
SELECT <columns> FROM <table> WHERE <column name> > <value>;
SELECT <columns> FROM <table> WHERE <column name> >= <value>;
Пример:
SELECT first_name, last_name FROM users WHERE date_of_birth < '1998-12-01';
SELECT title AS "Book Title", author AS Author FROM books WHERE year_released <= 2015;
SELECT name, description FROM products WHERE price > 9.99;
SELECT title FROM movies WHERE release_year >= 2000;
Более одного условия / More Than One Condition
Вы можете сравнить несколько значений в условии WHERE
. Если вы хотите проверить, что оба условия верны, используйте ключевое слово AND
, или одно из условий верно, используйте ключевое слово OR
.
SELECT <columns> FROM <table> WHERE <condition 1> AND <condition 2> …;
SELECT <columns> FROM <table> WHERE <condition 1> OR <condition 2> …;
Пример:
SELECT username FROM users WHERE last_name = "Chalkley" AND first_name = "Andrew";
SELECT * FROM products WHERE category = "Games Consoles" AND price < 400;
SELECT * FROM movies WHERE title = "The Matrix" OR title = "The Matrix Reloaded" OR title = "The Matrix Revolutions";
SELECT country FROM countries WHERE population < 1000000 OR population > 100000000;
Поиск в наборе значений / Searching in a Set of Values
SELECT <columns> FROM <table> WHERE <column> IN (<value 1>, <value 2>, …);
Пример:
SELECT name FROM islands WHERE id IN (4, 8, 15, 16, 23, 42);
SELECT * FROM products WHERE category IN ("eBooks", "Books", "Comics");
SELECT title FROM courses WHERE topic IN ("JavaScript", "Databases", "CSS");
SELECT * FROM campaigns WHERE medium IN ("email", "blog", "ppc");
Чтобы найти все строки, которых нет в наборе значений, вы можете использовать NOT IN
.
SELECT <columns> FROM <table> WHERE <column> NOT IN (<value 1>, <value 2>, …);
Пример:
SELECT answer FROM answers WHERE id IN (7, 42);
SELECT * FROM products WHERE category NOT IN ("Electronics");
SELECT title FROM courses WHERE topic NOT IN ("SQL", "NoSQL");
Поиск в диапазоне значений / Searching within a Range of Values
SELECT <columns> FROM <table> WHERE <column> BETWEEN <lesser value> AND <greater value>;
Пример:
SELECT * FROM movies WHERE release_year BETWEEN 2000 AND 2010;
SELECT name, description FROM products WHERE price BETWEEN 9.99 AND 19.99;
SELECT name, appointment_date FROM appointments WHERE appointment_date BETWEEN "2015-01-01" AND "2015-01-07";
Сопоставление с образцом / Pattern Matching
Размещение символа процента (%
) в любом месте строки в сочетании с LIKE
ключевым словом будет работать как подстановочный знак. Это означает, что его можно заменить любым количеством символов, включая ноль!
SELECT <columns> FROM <table> WHERE <column> LIKE <pattern>;
Пример:
SELECT title FROM books WHERE title LIKE "Harry Potter%Fire";
SELECT title FROM movies WHERE title LIKE "Alien%";
SELECT * FROM contacts WHERE first_name LIKE "%drew";
SELECT * FROM books WHERE title LIKE "%Brief History%";
Специальные ключевые слова PostgreSQL / PostgreSQL Specific Keywords
LIKE
в PostgreSQL чувствителен к регистру. Для поиска без учета регистра используйте ILIKE
.
SELECT * FROM contacts WHERE first_name ILIKE "%drew";
Отсутствующие значения / Missing Values
SELECT * FROM <table> WHERE <column> IS NULL;
Пример:
SELECT * FROM people WHERE last_name IS NULL;
SELECT * FROM vhs_rentals WHERE returned_on IS NULL;
SELECT * FROM car_rentals WHERE returned_on IS NULL AND location = "PDX";
Чтобы отфильтровать пропущенные значения, можно использовать IS NOT NULL
.
SELECT * FROM <table> WHERE <column> IS NOT NULL;
Examples
SELECT * FROM people WHERE email IS NOT NULL;
SELECT * FROM addresses WHERE zip_code IS NOT NULL;
Изменение данных с помощью SQL
Добавление строки в таблицу / Adding a Row to a Table
Вставка одной строки:
INSERT INTO <table> VALUES (<value 1>, <value 2>, …);
Это вставит значения в порядке следования столбцов в схеме.
Пример:
INSERT INTO users VALUES (1, "chalkers", "Andrew", "Chalkley");
INSERT INTO users VALUES (2, "ScRiPtKiDdIe", "Kenneth", "Love");
INSERT INTO movies VALUES (3, "Starman", "Science Fiction", 1984);
INSERT INTO movies VALUES (4, "Moulin Rouge!", "Musical", 2001);
Вставка одной строки со значениями в любом порядке:
INSERT INTO <table> (<column 1>, <column 2>) VALUES (<value 1>, <value 2>);
INSERT INTO <table> (<column 2>, <column 1>) VALUES (<value 2>, <value 1>);
Пример:
INSERT INTO users (username, first_name, last_name) VALUES ("chalkers", "Andrew", "Chalkley");
INSERT INTO users (first_name, last_name, username) VALUES ("Kenneth", "Love", "ScRiPtKiDdIe");
INSERT INTO movies (title, genre, year_released) VALUES ("Starman", "Science Fiction", 1984);
INSERT INTO movies (title, year_released, genre) VALUES ("Moulin Rouge!", 2001, "Musical");
Добавление нескольких строк в таблицу / Adding Multiple Rows to a Table
Вставка нескольких строк в один оператор:
INSERT INTO <table> (<column 1>, <column 2>, …)
VALUES
(<value 1>, <value 2>, …),
(<value 1>, <value 2>, …),
(<value 1>, <value 2>, …);
Пример:
INSERT INTO users (username, first_name, last_name)
VALUES
("chalkers", "Andrew", "Chalkley"),
("ScRiPtKiDdIe", "Kenneth", "Love");
INSERT INTO movies (title, genre, year_released)
VALUES
("Starman", "Science Fiction", 1984),
("Moulin Rouge!", "Musical", 2001);
Обновление всех строк в таблице / Updating All Rows in a Table
Оператор обновления для всех строк:
UPDATE <table> SET <column> = <value>;
Знак =
отличается от оператора равенства из условия WHERE
. Это assignment operator потому что вы присваиваете новое значение чему-то.
Пример:
UPDATE users SET password = "thisisabadidea";
UPDATE products SET price = 2.99;
Обновить несколько столбцов во всех строках:
UPDATE <table> SET <column 1> = <value 1>, <column 2> = <value 2>;
Пример:
UPDATE users SET first_name = "Anony", last_name = "Moose";
UPDATE products SET stock_count = 0, price = 0;
Обновление определенных строк / Updating Specific Rows
Оператор обновления для определенных строк:
UPDATE <table> SET <column> = <value> WHERE <condition>;
Пример:
UPDATE users SET password = "thisisabadidea" WHERE id = 3;
UPDATE blog_posts SET view_count = 1923 WHERE title = "SQL is Awesome";
Обновите несколько столбцов для определенных строк:
UPDATE <table> SET <column 1> = <value 1>, <column 2> = <value 2> WHERE <condition>;
Пример:
UPDATE users SET entry_url = "/home", last_login = "2016-01-05" WHERE id = 329;
UPDATE products SET status = "SOLD OUT", availability = "In 1 Week" WHERE stock_count = 0;
Удаление данных из всех строк таблицы / Removing Data from All Rows in a Table
Чтобы удалить все строки из таблицы:
DELETE FROM <table>;
Пример:
DELETE FROM logs;
DELETE FROM users;
DELETE FROM products;
Удаление определенных строк / Removing Specific Rows
Чтобы удалить определенные строки из таблицы:
DELETE FROM <table> WHERE <condition>;
Пример:
DELETE FROM users WHERE email = "andrew@teamtreehouse.com";
DELETE FROM movies WHERE genre = "Musical";
DELETE FROM products WHERE stock_count = 0;
Транзакции / Transactions
Отключите автофиксацию и начните транзакцию:
BEGIN TRANSACTION;
Или просто:
BEGIN;
Чтобы сохранить все результаты операторов после начала транзакции на диск:
COMMIT;
Чтобы сбросить состояние базы данных до начала транзакции:
ROLLBACK;
Отчетность с помощью SQL
Упорядочивание столбцов
Сортировка по критериям одного столбца:
SELECT * FROM <table name> ORDER BY <column> [ASC|DESC];
ASC
используется для упорядочения результатов в порядке возрастания.
DESC
используется для упорядочивания результатов в порядке убывания.
Examples:
SELECT * FROM books ORDER BY title ASC;
SELECT * FROM products WHERE name = "Sonic T-Shirt" ORDER BY stock_count DESC;
SELECT * FROM users ORDER BY signed_up_on DESC;
SELECT * FROM countries ORDER BY population DESC;
Сортировка по критериям нескольких столбцов:
SELECT * FROM <table name> ORDER BY <column> [ASC|DESC],
<column 2> [ASC|DESC],
…,
<column n> [ASC|DESC];
Приоритет отдается слева направо.
Examples:
SELECT * FROM books ORDER BY genre ASC,
title ASC;
SELECT * FROM books ORDER BY genre ASC,
year_published DESC;
SELECT * FROM users WHERE email LIKE "%@gmail.com"
ORDER BY last_name ASC,
first_name ASC;
Ограничение результатов
- SQLite, PostgreSQL и MySQL
Чтобы ограничить количество возвращаемых результатов, используйте LIMIT
ключевое слово.
SELECT <columns> FROM <table> LIMIT <# of rows>;
- MS SQL
Чтобы ограничить количество возвращаемых результатов, используйте TOP
ключевое слово.
SELECT TOP <# of rows> <columns> FROM <table>;
- Oracle
Чтобы ограничить количество возвращаемых результатов, используйте
ROWNUM
ключевое слово вWHERE
пункте.SELECT <columns> FROM <table> WHERE ROWNUM <= <# of rows>;
Перелистывание результатов
- SQLite, PostgreSQL и MySQL
Чтобы просмотреть результаты, вы можете либо использовать OFFSET
ключевое слово в сочетании с LIMIT
ключевым словом или просто с одним LIMIT.
SELECT <columns> FROM <table> LIMIT <# of rows> OFFSET <skipped rows>;
SELECT <columns> FROM <table> LIMIT <skipped rows>, <# of rows>;
- MS SQL и Oracle
Чтобы просмотреть результаты, вы можете либо использовать OFFSET
ключевое слово в сочетании с FETCH
ключевым словом. Нельзя использовать с TOP
.
SELECT <columns> FROM <table> OFFSET <skipped rows> ROWS FETCH NEXT <# of rows> ROWS ONLY;
Определения синтаксиса
-
Keywords: Команды, выдаваемые базе данных. Данные, представленные в запросах, не изменяются.
-
Operators: Выполняет сравнения и простые манипуляции
-
Functions: Представление данных по-разному посредством более сложных манипуляций
-
Arguments и Parameters: Значения, передаваемые в функции.
Функция выглядит так:
<function name>(<value or column>)
Examples:
SELECT UPPER("Andrew Chalkley");
SELECT UPPER(name) FROM passport_holders;
Объединение строк
- SQLite, PostgreSQL и Oracle
Используйте оператор конкатенации ||
.
SELECT <value or column> || <value or column> || <value or column> FROM <table>;
- MS SQL
Используйте оператор конкатенации +
.
SELECT <value or column> + <value or column> + <value or column> FROM <table>;
- MySQL, PostgreSQL и MS SQL
Используйте CONCAT()
функцию.
SELECT CONCAT(<value or column>, <value or column>, <value or column>) FROM <table>;
Нахождение длины строк
Чтобы получить длину значения или столбца, используйте LENGTH()
функцию.
SELECT LENGTH(<value or column>) FROM <tables>;
Изменение регистра строк
Использовать UPPER()
функцию для преобразования текста в верхний регистр.
SELECT UPPER(<value or column>) FROM <table>;
Использовать LOWER()
функцию для перевода текста в нижний регистр.
SELECT LOWER(<value or column>) FROM <table>;
Создать выдержки с подстрокой
Чтобы создать меньшие строки из большего фрагмента текста, вы можете использовать SUBSTR()
функцию или функцию подстроки.
SELECT SUBSTR(<value or column>, <start>, <length>) FROM <table>;
-
\<start> : Specifies where to start in the string
-
if
is 0 (zero), then it is treated as 1. -
if
is positive, then the function counts from the beginning of string to find the first character. -
if
is negative, then the function counts backward from the end of string.
-
-
\<finish> : length of the desired substring
SELECT SUBSTR('abcdefg', 3,4);
OUTPUT: cdef
SELECT SUBSTR('abcdefg', -5,4);
OUTPUT: cdef
Замена частей текста
Чтобы заменить фрагмент строки текста в большом тексте, вы можете использовать REPLACE()
функцию.
SELECT REPLACE(<original value or column>, <target string>, <replacement string>) FROM <table>;
Подсчет результатов
Для подсчета строк вы можете использовать COUNT()
функцию.
SELECT COUNT(*) FROM <table>;
Для подсчета уникальных записей используйте DISTINCT
:
SELECT COUNT(DISTINCT <column>) FROM <table>;
Для подсчета агрегированных строк с общими значениями используйте метод GROUP BY
:
SELECT COUNT(<column>) FROM <table> GROUP BY <column with common value>;
Получение итогов
Чтобы суммировать числовые столбцы, используйте SUM()
функцию.
SELECT SUM(<numeric column) FROM <table>;
SELECT SUM(<numeric column) AS <alias> FROM <table>
GROUP BY <another column>
HAVING <alias> <operator> <value>;
Вычисление средних значений
Чтобы получить среднее значение числового столбца, используйте AVG()
функцию.
SELECT AVG(<numeric column>) FROM <table>;
SELECT AVG(<numeric column>) FROM <table> GROUP BY <other column>;
Нахождение максимального и минимального значений
Чтобы получить максимальное значение числового столбца, используйте MAX()
функцию.
SELECT MAX(<numeric column>) FROM <table>;
SELECT MAX(<numeric column>) FROM <table> GROUP BY <other column>;
Чтобы получить минимальное значение числового столбца, используйте MIN()
функцию.
SELECT MIN(<numeric column>) FROM <table>;
SELECT MIN(<numeric column>) FROM <table> GROUP BY <other column>;
Математические операторы
*
Умножить/
Разделять+
Добавлять-
ВычестьSELECT <numeric column> <mathematical operator> <numeric value> FROM <table>;
Актуальные даты и время
- SQLite
Чтобы получить текущую дату, используйте: DATE("now")
Чтобы получить текущее время, используйте: TIME("now")
Чтобы получить текущую дату и время: DATETIME("NOW")
- MS SQL
Чтобы получить текущую дату, используйте: CONVERT(date, GETDATE())
Чтобы получить текущее время, используйте: CONVERT(time, GETDATE())
Чтобы получить текущую дату и время: GETDATE()
- MySQL
Чтобы получить текущую дату, используйте: CURDATE()
Чтобы получить текущее время, используйте: CURTIME()
Чтобы получить текущую дату и время: NOW()
- Oracle и PostgreSQL
Чтобы получить текущую дату, используйте: CURRENT_DATE
Чтобы получить текущее время, используйте: CURRENT_TIME
Чтобы получить текущую дату и время: CURRENT_TIMESTAMP
Вычисление дат
Смотрите сайты документации:
Форматирование дат
Смотрите сайты документации:
Запросы к реляционным базам данных
СОЕДИНЕНИЯ SQL / SQL JOINs
JOIN объединяет связанные данные из нескольких таблиц в набор результатов.
Два наиболее распространенных типа соединений:
- INNER JOIN
- OUTER JOIN
ВНУТРЕННИЕ СОЕДИНЕНИЯ / INNER JOINs
INNER JOIN возвращает строки, которые совпадают из обеих таблиц.
SELECT <columns> FROM <table 1>
INNER JOIN <table 2> ON <table 1>.<column> = <table 2>.<column>;
SELECT <columns> FROM <table 1> AS <table 1 alias>
INNER JOIN <table 2> AS <table 2 alias> ON <table 1 alias>.<column> = <table 2 alias>.<column>;
Пример:
SELECT product_name, category FROM products
INNER JOIN product_categories ON products.category_id = product_categories.id;
SELECT products.product_name, product_categories.category FROM products
INNER JOIN product_categories ON products.category_id = product_categories.id;
SELECT p.product_name, c.category FROM products AS p
INNER JOIN product_categories AS c ON p.category_id = c.id;
INNER JOIN объединение нескольких таблиц:
SELECT <columns> FROM <table 1>
INNER JOIN <table 2> ON <table 1>.<column> = <table 2>.<column>
INNER JOIN <table 3> ON <table 1>.<column> = <table 3>.<column>;
Пример:
SELECT users.full_name, sales.amount, products.name FROM sales
INNER JOIN users ON sales.user_id = users.id
INNER JOIN products ON sales.product_id = products.id;
ВНЕШНИЕ СОЕДИНЕНИЯ / OUTER JOINs
Есть 3 типа OUTER JOIN:
- LEFT OUTER JOIN - СОЕДИНЯЕТ все совпадающие данные и все не совпадающие строки из таблицы left в запросе
- RIGHT OUTER JOIN - СОЕДИНЯЕТ все совпадающие данные и все не совпадающие строки из таблицы right в запросе
- FULL OUTER JOIN - СОЕДИНЯЕТ все совпадающие данные, а затем все несовпадающие строки из обеих таблиц.
SELECT <columns> FROM <left table>
LEFT OUTER JOIN <right right> ON <left table>.<column> = <right table>.<column>;
SELECT <columns> FROM <left table> AS <left alias>
LEFT OUTER JOIN <right table> AS <right alias>
ON <left alias>.<column> = <right alias>.<column>;
Example:
Если вы хотите получить количество продуктов для каждой категории, даже для категорий без продуктов, OUTER JOIN
- лучшее решение.
Следующие два примера дадут одинаковые результаты, однако один из них будет LEFT OUTER JOIN
, а другой — RIGHT OUTER JOIN
.
SELECT categories.name, COUNT(products.id) AS "Product Count" FROM categories
LEFT OUTER JOIN products ON categories.id = products.category_id;
SELECT categories.name, COUNT(products.id) AS "Products Count" FROM products
RIGHT OUTER JOIN categories ON categories.id = products.category_id;
Set операции / Set Operations
Операции набора объединяют данные в один набор на основе определений столбцов и данных, содержащихся в каждом столбце.
Четыре операции над множествами:
- UNION
- UNION ALL
- INTERSECT
- EXCEPT
Количество столбцов должно совпадать. Если количество столбцов не совпадает, это приведет к ошибке.
<query 1> <set operation> <query 2>
SELECT <column> FROM <table 1> <set operation> SELECT <column> FROM <table 2>;
SELECT <column>, <column> FROM <table 1> <set operation> SELECT <column>, <column> FROM <table 2>;
Примеры объединения / UNION Examples
Объединения возвращают все различные значения из обоих наборов данных без дубликатов.
Получите список уникальных ресторанов как в северных, так и в южных торговых центрах.
SELECT store FROM mall_south WHERE type = "restaurant"
UNION
SELECT store FROM mall_north WHERE type = "restaurant";
Получите список уникальных классов, преподаваемых в двух школах. Упорядочить их по имени класса.
SELECT evening_class FROM school_1 UNION SELECT evening_class FROM school_2
ORDER BY evening_class ASC;
Объединение всех / UNION ALL
Union all возвращает все значения из обоих наборов данных — с дубликатами.
Получить список всех имен для мальчиков и девочек и заказать их по имени.
SELECT boy_name AS name FROM boy_baby_names
UNION ALL
SELECT girl_name AS name FROM girl_baby_names
ORDER by name;
Пересечения / INTERSECT
Возвращает только значения, которые есть в обоих наборах данных.
Получить список классов, предлагаемых в обеих школах.
SELECT evening_class FROM school_1 INTERSECT SELECT evening_class FROM school_2
ORDER BY evening_class ASC;
Получите список ресторанов в обоих торговых центрах.
SELECT store FROM mall_south WHERE type = "restaurant"
INTERSECT
SELECT store FROM mall_north WHERE type = "restaurant";
Исключения / EXCEPT
Возвращает данные из первого набора данных, которых нет во втором.
Получить список местных магазинов в торговом центре.
SELECT store FROM mall
EXCEPT
SELECT store FROM all_stores WHERE type = "national"
Подзапросы / Subqueries
Подзапросы — это запросы внутри запросов. Подзапрос также можно назвать внутренним запросом, а "родительский" запрос называется внешним запросом.
Существует два основных способа использования подзапроса:
- В
IN
условии - Как производная или временная таблица
Подзапрос в IN
условии должен иметь только один столбец.
SELECT <columns> FROM <table 1> WHERE <table 1>.<column> IN (<subquery>);
SELECT <columns> FROM <table 1>
WHERE <table 1>.<column> IN (SELECT <a single column> FROM <table 2> WHERE <condition>);
Пример:
Получите список имен и адресов электронной почты пользователей, которые потратили более 100 долларов за одну транзакцию.
SELECT name, email FROM users
WHERE id IN (SELECT DISTINCT(user_id) FROM sales WHERE saleAmount > 100);
// OR
SELECT name, email FROM users
INNER JOIN (SELECT DISTINCT(user_id) FROM sales WHERE saleAmount > 100) AS best_customers
ON users.id = best_customers.user_id;
Получите список имен и адресов электронной почты пользователей, которые в общей сложности потратили более 1000 долларов.
SELECT name, email FROM users WHERE id IN (SELECT user_id FROM sales WHERE SUM(saleAmount) > 1000 GROUP BY user_id);
// OR
SELECT name, email, total FROM users
INNER JOIN (SELECT user_id, SUM(saleAmount) AS total FROM sales WHERE total > 1000 GROUP BY user_id) AS ultimate_customers
ON users.id = ultimate_customers.user_id;