Язык SQL работает со множествами. Это важно понимать при работе с несколькими таблицами и вложенными запросами. Обычно эти множества можно нарисовать как круги, чтобы понять что нам нужно получить (заштриховать требуемые области пересечений). Таблицы же можно фильтровать и сортировать.

SQL в деталях довольно сильно разный в разных базах. Такие вещи как достать год из даты обычно весьма специфичны для каждой базы и даже типа колонки.

Для быстрых запросов нужны индексы. Они ускоряют извлечение данных, но замедляют запись и увеличивают размер базы, поэтому нужен баланс.

Псевдокод таблиц для примера запросов:

users: id, name, age
teams: id, name, create_at
users_in_groups: user_id, group_id

Вывести все группы пользователей с больше, чем 5-ью совершеннолетними пользователями, по уменьшению кол-ва совершеннолетних пользователей:

SELECT
  t.name as team_name,
  COUNT(u.id) as amount
FROM
  teams t,
  users u,
  users_in_teams u2t
WHERE
  u2t.user_id = u.id
  AND u2t.team_id = t.id
  AND u.age > 18
GROUP BY t.name
HAVING COUNT(u.id) > 5
ORDER BY COUNT(u.id) DESC

Вывести группы по алфавитному порядку с кол-вом пользователей (выводить даже 0):

SELECT
  t.name as team_name,
  COUNT(u.id) as amount
FROM
  teams t
LEFT JOIN users_in_teams u2t ON u2t.team_id = t.id
LEFT JOIN users u ON u2t.user_id = u.id
GROUP BY t.name
ORDER BY t.name ASC

Вывести группы по алфавитному порядку с кол-вом совершеннолетних пользователей (выводить даже 0):

SELECT
  t.name as team_name,
  IFNULL(team_with_amount.amount, 0) as amount
FROM teams t
LEFT JOIN (SELECT
    t2.id as team_id,
    t2.name as team_name,
    COUNT(u.id) as amount
  FROM
    teams t2,
    users u,
    users_in_teams u2t
  WHERE
    u2t.user_id = u.id
    AND u2t.team_id = t2.id
    AND u.age > 18
  GROUP BY t2.id, t2.name) as team_with_amount
ON t.id = team_with_amount.team_id
ORDER BY t.name ASC

Если можете прочитать и написать такие SQL-запросы, то обычно такого уровня понимания достаточно. Если сейчас непонятно, то лучше подучить это немного – на собеседованиях практически всегда что-то подобное спрашивают. Да и на практике оно нужно.

ACID свойства транзакций:

  • Atomicity (атомарность) - применилась или откатилась
  • Consistency (согласованность) - транзакция не нарушает согласованности данных
  • Isolation (изолированность) - как если бы транзакции шли последовательно
  • Durability (долговечность) - если применилась, то невозможно потерять данные

Ну и уровни изоляций:

  • Read uncommitted (чтение незафиксированных данных) – все плохо, но без блокировок
  • Read committed (чтение фиксированных данных) – по умолчанию – изменения строк могут появляться внутри транзакции, если другая транзакция закончилась
  • Repeatable read (повторяющееся чтение) – но новые строки могут появляться внутри транзакции от других транзакций
  • Serializable (упорядочиваемость) – все хорошо, но медленно