Трюк дня. Получить id покупки с максимальной value для каждого customer.
Например, есть таблица:
id customer value
1 Alex 5
2 Sam 1
3 Sam 3
В результате нужно получить следующее:
id customer value
1 Alex 5
3 Sam 3
В PostgreSQL можно использовать оператор DISTINCT ON:
customer,
value
#tips
А какие варианты решения вы знаете?
Например, есть таблица:
id customer value
1 Alex 5
2 Sam 1
3 Sam 3
В результате нужно получить следующее:
id customer value
1 Alex 5
3 Sam 3
В PostgreSQL можно использовать оператор DISTINCT ON:
SELECT
DISTINCT ON(customer)
id,customer,
value
FROM table
ORDER BY customer, value
DESC, id
#tips
А какие варианты решения вы знаете?
👍3🔥2
Трюк дня. Найти записи с граничными значениями без соединения таблицы на саму себя
Один из вариантов - это сначала найти максимальное значение для каждого ID с помощью GROUP BY, и затем соединить таблицу с самой собой по ID и max значению.
Но есть способ лучше:
#tips
Один из вариантов - это сначала найти максимальное значение для каждого ID с помощью GROUP BY, и затем соединить таблицу с самой собой по ID и max значению.
Но есть способ лучше:
SELECT
dat2
.*
FROM
(
SELECT
dat.*,
CASE WHEN (num = MAX(num) OVER (PARTITION BY id)) THEN 'y' ELSE 'n' END AS max_num
FROM current_table dat
) dat2
WHERE max_num = 'y'
#tips
👍9💩4
Трюк дня. Удаление лишних пробелов в строке с использованием REGEX.
Предположим, есть строка, содержащая такой текст:
Требуется удалить из строки лишние пробелы.
Решение:
Используйте функцию REGEXP_REPLACE:
#tips
Предположим, есть строка, содержащая такой текст:
This is a test string
Требуется удалить из строки лишние пробелы.
Решение:
Используйте функцию REGEXP_REPLACE:
SELECT
REGEXP_REPLACE('This is a test string','( ){2,}',' ');
#tips
👍12
Трюк дня. Найти второе место по зарплате
Напишите SQL-запрос для получения из таблицы (
Например, для таблицы на картинке выше такой запрос должен вернуть
Решение будет вечером.
#tips
Напишите SQL-запрос для получения из таблицы (
employee
) с зарплатами записи, содержащие вторую по размеру заработную плату.Например, для таблицы на картинке выше такой запрос должен вернуть
200
. Если в таблице нет значения, меньшего, чем самая высокая зарплата — запрос должен вернуть null
.Решение будет вечером.
#tips
Трюк дня. Найти второе место по зарплате. Решение.
Решение 1: использование
Здесь выбирается самое большое значение зарплаты, не равное максимальной зарплате, полученной по всей таблице. В результате мы и получаем то, что нужно — вторую по величине зарплату.
#tips
Решение 1: использование
IFNULL
и OFFSET
• IFNULL(expression, alt)
: эта функция возвращает аргумент expression
в случае, если он не равен null
. В противном случае возвращается аргумент alt
. Мы используем эту функцию чтобы возвратить null
, если в таблице не окажется искомого значения. • OFFSET
: этот оператор используется с ORDER BY
для того чтобы отбросить первые n
строк. Используется для получения второго по величине значения. SELECT
IFNULL(
(SELECT DISTINCT salary
FROM employee
ORDER BY salary DESC
LIMIT 1
OFFSET 1
), null) AS sec_salary
FROM employee
LIMIT 1
Решение 2: использование MAX
Здесь выбирается самое большое значение зарплаты, не равное максимальной зарплате, полученной по всей таблице. В результате мы и получаем то, что нужно — вторую по величине зарплату.
SELECT
MAX(salary) AS sec_salary
FROM Employee
WHERE salary != (SELECT MAX(salary) FROM employee)
#tips
❤5👍4🤔3
Трюк дня. Сравнение с предыдущим
Напишите SQL-запрос, который находит в таблице
Решение будет завтра.
#tips
Напишите SQL-запрос, который находит в таблице
weather
все даты (идентификаторы дат), когда температура была бы выше температуры на предшествующие им даты. То есть, нас интересуют даты, в которые «сегодняшняя» температура выше «вчерашней».Решение будет завтра.
#tips
👍1
Трюк дня. Сравнение с предыдущим. Решение.
Решение: использование
Если сформулировать обычным языком следующий запрос, то окажется, что он выражает следующую идею: нужно выбрать такие идентификаторы, чтобы температура, соответствующая представляемым ими датам, была бы больше, чем температура на «вчерашние» по отношению к ним даты.
Решение: использование
DATEDIFF
DATEDIFF
: эта функция вычисляет разницу между двумя датами. Она используется для того, чтобы обеспечить сравнение именно «сегодняшних» и «вчерашних» температур.Если сформулировать обычным языком следующий запрос, то окажется, что он выражает следующую идею: нужно выбрать такие идентификаторы, чтобы температура, соответствующая представляемым ими датам, была бы больше, чем температура на «вчерашние» по отношению к ним даты.
SELECT DISTINCT a.Id#tips
FROM Weather a, Weather b
WHERE a.Temperature > b.Temperature
AND DATEDIFF(a.Recorddate, b.Recorddate) = 1
👍7😱2👎1
Трюк дня. Ранг без
Решение будет завтра.
#tips
RANK()
Напишите SQL-запрос, который будет ранжировать scores
из таблицы scores
без использования оконной функции. Одинаковые scores
должны иметь одинаковый ранг. Ранг, следующий за одинаковыми scores
, должен быть следущий целым числом (см. ожидаемый результат на картинке выше). Решение будет завтра.
#tips
Трюк дня. Ранг без RANK(). Решение.
Соединим таблицу саму на себя, сравнивая
Подсчитаем все уникальные значения объединённых
Соединим таблицу саму на себя, сравнивая
score
.Подсчитаем все уникальные значения объединённых
score
. Это и даёт эквивалент DENSE_RANK()
. SELECT s1.score, count(DISTINCT s2.score) AS score_rank
FROM scores s1
JOIN scores s2
ON s1.score <= s2.score
GROUP BY s1.id, s1.score
ORDER BY 1 DESC
#tips👍7
Трюк дня. Получить список аккаунтов в MySQL с помощью запроса
Используйте код:
Результат будет следующего вида :
+------+
| User |
+------+
| root |
+------+
| user2 |
+------+
#tips
А как можно получить список аккаунтов в других СУБД?
Используйте код:
SELECT User FROM mysql.user;
Результат будет следующего вида :
+------+
| User |
+------+
| root |
+------+
| user2 |
+------+
#tips
А как можно получить список аккаунтов в других СУБД?
Трюк дня. Простые числа
Напишите PostgreSQL-запрос, который возвратит простые числа от 2 до 1000.
Решение будет вечером.
#tips
Напишите PostgreSQL-запрос, который возвратит простые числа от 2 до 1000.
Решение будет вечером.
#tips
Трюк дня. Простые числа. Решение.
Простое число - натуральное (целое положительное) число, имеющее ровно два различных натуральных делителя — единицу и самого себя.
Для начала создадим набор чисел от 2 до 1000 с помощью функции
Простое число - натуральное (целое положительное) число, имеющее ровно два различных натуральных делителя — единицу и самого себя.
Для начала создадим набор чисел от 2 до 1000 с помощью функции
generate_series.
Затем с помощью NOT EXISTS
(которое можно, модифицировав, заменить на JOIN
) мы соединяем таблицу саму на себя и затем выбираем только те значения, для которых ни одно деление на меньшее число не дает остаток 0. WITH x AS (
SELECT * FROM generate_series( 2, 1000 ) x
)
SELECT x.x
FROM x
WHERE NOT EXISTS (
SELECT 1 FROM x y
WHERE x.x > y.x AND x.x % y.x = 0
);
#tips👍5
Трюк дня. Выбрать значения, которые соответствуют одному из нескольких шаблонов
Из PostgreSQL таблицы
Решение будет завтра.
#tips
Из PostgreSQL таблицы
customers
выберите только тех пользователей, текстовое поле phone
которых содержит либо +011
, либо +044
, либо +099
.Решение будет завтра.
#tips
👍1
Трюк дня. Выбрать значения, которые соответствуют одному из нескольких шаблонов. Решение
SELECT *#tips
FROM customers
WHERE phone LIKE ANY('{%+011%,%+044%,%+099%}');
Трюк дня. Выборка записей из таблицы при различных условиях
Из MySQL таблицы
Исходная таблица:
#tips
Из MySQL таблицы
customers
выберите только тех, которые:•
имеют тип = ‘Sal
’ или ‘Adv
’ И разница между датами mod
и trans
>=365 дней; •
имеют тип = ‘Cus’ И разница между датами mod
и trans
>=14 дней.Исходная таблица:
type mod trans
Cus 2022-01-01 2022-12-01
Sal 2022-08-01 2021-05-01
Adv 2022-05-01 2022-04-01
Cus 2022-05-01 2022-04-01
Ожидаемые результат:type mod trans
Sal 2022-08-01 2021-05-01
Cus 2022-05-01 2022-04-01
Решение будет вечером. #tips
👍1
Трюк дня. Выборка записей из таблицы при различных условиях. Решение
SELECT
DAT.*
FROM customer DAT
WHERE DATEDIFF(mod,trans)>=
CASE WHEN type IN('Sal', 'Adv') THEN 365
WHEN type IN('Cus') THEN 14
ELSE NULL END;
#tipsТрюк дня. Найти медиану
Предположим, есть таблица, содержащая в столбце sales такие записи:
2, 1, 3, 8, 7, 5.
Необходимо найти медиану для данного столбца.
Решение:
В PostgreSQL используйте функцию percentile_count:
В Oracle используйте функцию MEDIAN:
Однако в MySQL подобных функций нет. Поэтому медиану нужно вычислять самостоятельно.
Напомним: медиана - это число, которое находится в середине набора чисел, отсортированных по возрастанию.
#tips
Предположим, есть таблица, содержащая в столбце sales такие записи:
2, 1, 3, 8, 7, 5.
Необходимо найти медиану для данного столбца.
Решение:
В PostgreSQL используйте функцию percentile_count:
SELECT percentile_cont (0.5) WITHIN GROUP (ORDER BY sales) FROM table;В MS SQL также используйте функцию percentile_count:
SELECT percentile_cont (0.5) WITHIN GROUP (ORDER BY sales) OVER (PARTITION BY 1) FROM table;В PARTITION BY можно внести столбец, по которому группируются данные. В данном случае мы использовали 1, чтобы посчитать медиану по всем данным столбца.
В Oracle используйте функцию MEDIAN:
SELECT MEDIAN (sales) OVER (PARTITION BY 1) FROM table;
Однако в MySQL подобных функций нет. Поэтому медиану нужно вычислять самостоятельно.
Напомним: медиана - это число, которое находится в середине набора чисел, отсортированных по возрастанию.
/*задаем переменную row_index = -1, чтобы отсчет индекса начался с 0 */Ответ: медиана = 4.
SET @row_index := -1;
/*находим среднее двух значений в центре отсортированного набора. Охватывает те случаи, когда общее число записей четное*/
SELECT AVG (subq.sales) as median_value
FROM (
SELECT @row_index:=@row_index + 1 AS row_index, sales
FROM table
ORDER BY sales
) AS subq
WHERE subq.row_index
/*выбираем только значения в центре: одно если число записей нечетное и два если четное*/
IN (FLOOR(@row_index / 2) , CEIL(@row_index / 2));
#tips
❤2
Трюк дня. Изменить тип поля с CHARACTER на NUMERIC в PostgreSQL
В PostgreSQL таблице
Напишите запрос, который приведёт данную колонку к типу
Решение будет позже вечером.
#tips
В PostgreSQL таблице
customers
колонка age
имеет тип CHARACTER(20)
. Напишите запрос, который приведёт данную колонку к типу
NUMERIC (10,0)
.Решение будет позже вечером.
#tips
Трюк дня. Изменить тип поля с CHARACTER на NUMERIC в PostgreSQL. Решение
ИЛИ
ALTER TABLE
customers
ALTER
COLUMN age
TYPE NUMERIC (10,0)
USING age::NUMERIC;
ИЛИ
ALTER TABLE
customers
ALTER
COLUMN age
TYPE NUMERIC (10,0)
USING CAST(age AS NUMERIC);
#tipsТрюк дня. SQL - Сортировка зеркальных строк
#tips
SELECT game, count(game)
FROM (
select
case when a < b then concat(a, '-' , b)
else concat(b , '-', a ) end as game
from data
) as t
GROUP by game|
#tips