Шпаргалка по основам 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

Подзапросы — это запросы внутри запросов. Подзапрос также можно назвать внутренним запросом, а "родительский" запрос называется внешним запросом.

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

  1. В IN условии
  2. Как производная или временная таблица

Подзапрос в 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;
Читать по теме
Интересные статьи