SQLinfo.ru - Все о MySQL

Форум пользователей MySQL

Задавайте вопросы, мы ответим

Вы не зашли.

#1 10.06.2020 17:25:41

Катерина94
Участник
Зарегистрирован: 08.06.2020
Сообщений: 5

Чем заменить LIMIT?

Помогите, пожалуйста, решить.
По заданию, не могу использовать LIMIT, нужно заменить на что-то по стандарту Mysql.

Задача: Вывести имя сотрудника, получающего третью по величине зарплату в организации .

таблица по сотрудникам (employee):
id - число, первичный ключ
department_id - число, внешний ключ на таблицу department
chief_id - число, внешний ключ на саму таблицу employee
name - строка
salary - число

Мое стандартное работающее решение с LIMIT было бы таким:

SELECT name, MAX(salary)
FROM employee
GROUP BY salary
ORDER BY salary DESC
LIMIT 2, 1;

Неактивен

 

#2 10.06.2020 17:29:47

deadka
Администратор
Зарегистрирован: 14.11.2007
Сообщений: 2419

Re: Чем заменить LIMIT?

Здравствуйте.
А в чем проблема с использованием limit?
Можно, конечно, не использовать limit вовсе - то есть вытащить все данные на клиенте и там уже взять нужный элемент, но зачем?


Зеленый свет для слабаков, долги отдают только трусы, тру гики работают только в консоли...

Неактивен

 

#3 10.06.2020 17:57:11

Катерина94
Участник
Зарегистрирован: 08.06.2020
Сообщений: 5

Re: Чем заменить LIMIT?

Такое задание от преподавателя , использовать только стандарт.

Неактивен

 

#4 10.06.2020 18:23:18

deadka
Администратор
Зарегистрирован: 14.11.2007
Сообщений: 2419

Re: Чем заменить LIMIT?

Хм, а какой стандарт имеется в виду?
Спросите у преподавателя, какой именно стандарт ему нужен. ansi или какой?
Или покажите содержимое
https://en.wikipedia.org/wiki/Select_(SQL)#Limiting_result_rows
этой ссылки ему - пусть скажет, какой метод его устроит. И чтобы в mysql работал.

Потому что решение из стандарта ansi 2008

Select *
from {table}
order by {unique_key}
OFFSET {begin_base_0} ROWS
FETCH NEXT {rows} ROWS ONLY

в mysql, судя по всему, не представлено.

Или же - как я говорил чуть выше - вытащить на клиент всех и на клиенте отобрать 3-ю по счету зп.
Но это так себе решение - ибо сотрудников может быть много.

Можно, конечно, еще извратиться и что-то такое изобразить (LIMIT нам использовать запрещено, да? smile ).

SELECT id from `employee` WHERE salary = (SELECT max(salary) FROM (SELECT max(salary) FROM salary where salary NOT IN (SELECT max(salary) FROM `employee`)));

но это если все зарплаты разные.

И обязательно расскажите пожалуйста результат разговора с преподатавателем, аж на интересно стало, какой запрос он от Вас ждёт и какой стандарт надо использовать.
Запрет на использование LIMIT, честно говоря, ни в ВУЗЕ ни в работе не встрел.


Зеленый свет для слабаков, долги отдают только трусы, тру гики работают только в консоли...

Неактивен

 

#5 12.06.2020 02:04:27

Катерина94
Участник
Зарегистрирован: 08.06.2020
Сообщений: 5

Re: Чем заменить LIMIT?

deadka, спасибо Вам)) Да, потом обязательно напишу, уже самой интересно! big_smile Как он сказал, имеется в виду стандарт Mysql, типа LIMIT - это конечно хорошо, но это не стандарт, а нужно уметь работать по стандарту, поэтому думайте. На следующей неделе узнаю ответ) На клиент тоже не для меня сейчас решение, да и зп там подразумевается, что могут быть одинаковые, так что непонятно.

Неактивен

 

#6 12.06.2020 03:32:27

deadka
Администратор
Зарегистрирован: 14.11.2007
Сообщений: 2419

Re: Чем заменить LIMIT?

Стандарт mysql? Попросите его ссылочку на "стандарт mysql" smile.
В mysql limit имеется - вот можно ткнуть его в официальную документацию
https://dev.mysql.com/doc/refman/8.0/en … ation.html
, официальная документация от производителя СУБД как бе.

На клиент и одинаковые зп - да, это все так себе варианты, но Вы выводИте на чистую воду этого преподавателя Вашего, требуйте ссылки, пруфы, объяснения про этот загадочный стандарт :-).
Удачи, обязательно отпишитесь, как выясните что же за такой коварный стандарт mysql он имеет в виду, с которым limit нельзя использовать.

Еще спросите - может быть он оконные функции имел в виду? Правда это некрасиво, они совсем недавно появились-то в mysql
(с версии 8.0 ЕМНИП)

https://www.mysqltutorial.org/mysql-win … -function/

SELECT
    `name`,
    `salary`,
    NTH_VALUE(`name`, 2) OVER  ( ORDER BY `salary` DESC  ) second_highest_salary
FROM
    `employee`;


Попробуйте этот вариант? Если у Вас mysql 8.0

P. S. Приведенный Вами вариант в начале поста с лимитом несколько некорректный (изучите https://sqlinfo.ru/articles/info/18.html),
Если зарплаты разные, то:

SELECT name, salary FROM employee ORDER BY salary DESC LIMIT 2, 1;

Если же могут совпадать то да, нужна группировка.

SELECT salary FROM employee GROUP BY salary ORDER BY salary DESC LIMIT 2, 1;

Вот так точно сработает (и стандарт ansi соблюден), но без имени сотрудника.


Зеленый свет для слабаков, долги отдают только трусы, тру гики работают только в консоли...

Неактивен

 

#7 12.06.2020 03:44:20

deadka
Администратор
Зарегистрирован: 14.11.2007
Сообщений: 2419

Re: Чем заменить LIMIT?

P. S. Кстати говоря всё же можно без лимита, уже просто из спортивного интересаsmile.

В запросе используете вспомогательную колонку, которая выводит то, насколько эта зарплата велика относительно остальных и отсекаете все записи кроме той, у которой это значение равно 2 (у самого зажиточного сотрудника значение этой колонки будет 0, у самого бедного - соответственно самое крупное, в нашем случае 4)

create table _(id int, `name` text, salary int);

insert into _ values(6,'f',500),(5,'e',500),(4,'d',400),(3,'c',300),(1,'a',100),(2,'b',200);

select t1.* from _ t1 where (select count(distinct salary) from _ t2 where t2.salary > t1.salary) = 2;


Вывод: 3 c 300;

Но опять же слабо мне верится, что именно этого от Вас ждут.


Зеленый свет для слабаков, долги отдают только трусы, тру гики работают только в консоли...

Неактивен

 

#8 12.06.2020 05:54:22

vasya
Архат
MySQL Authorized Developer
Откуда: Орел
Зарегистрирован: 07.03.2007
Сообщений: 5827

Re: Чем заменить LIMIT?

to deadka,
count(distinct salary) -- зарплаты ведь могут быть не уникальны.

to Катерина94,
посмотрите https://sqlinfo.ru/articles/info/45.html
кроме уже указанных решений вам подойдут ещё  2-ой и 5-ый способ

Неактивен

 

#9 12.06.2020 14:26:49

deadka
Администратор
Зарегистрирован: 14.11.2007
Сообщений: 2419

Re: Чем заменить LIMIT?

vasya, спасибо за поправку, тут действительно нужен distinct count(salary) вместо count(*) в моём варианте.

5-й способ - тут преподаватель LIMIT порезал, а ты пользовательские переменные предлагаешь? :-)


Зеленый свет для слабаков, долги отдают только трусы, тру гики работают только в консоли...

Неактивен

 

#10 16.06.2020 09:16:06

vasya
Архат
MySQL Authorized Developer
Откуда: Орел
Зарегистрирован: 07.03.2007
Сообщений: 5827

Re: Чем заменить LIMIT?

Катерина94,
появились ли у вас новости от преподавателя?

и чтобы не флудить, решение 2-ым способом из https://sqlinfo.ru/articles/info/45.html :

mysql> select * from _;
+------+------+--------+
| id   | name | salary |
+------+------+--------+
|    6 | f    |    500 |
|    5 | e    |    500 |
|    4 | d    |    400 |
|    3 | c    |    300 |
|    1 | a    |    100 |
|    2 | b    |    200 |
|    7 | x    |    300 |
+------+------+--------+
7 rows in set (0.00 sec)

mysql> select t1.* from _ t1 join _ t2 on t2.salary >= t1.salary group by t1.id having count(distinct t2.salary) = 3;
+------+------+--------+
| id   | name | salary |
+------+------+--------+
|    3 | c    |    300 |
|    7 | x    |    300 |
+------+------+--------+
2 rows in set (0.00 sec)

mysql> set @@sql_mode='only_full_group_by';
Query OK, 0 rows affected (0.00 sec)

mysql> select t1.* from _ t1 join _ t2 on t2.salary >= t1.salary group by t1.id having count(distinct t2.salary) = 3;
ERROR 1055 (42000): Expression #2 of SELECT list is not in GROUP BY clause and contains nonaggregated column 'test.t1.name' which is not functionally dependent on columns
 in GROUP BY clause; this is incompatible with sql_mode=only_full_group_by

mysql> select * from _ where id in(select t1.id from _ t1 join _ t2 on t2.salary >= t1.salary group by t1.id having count(distinct t2.salary) = 3);
+------+------+--------+
| id   | name | salary |
+------+------+--------+
|    3 | c    |    300 |
|    7 | x    |    300 |
+------+------+--------+
2 rows in set (0.00 sec)

Неактивен

 

Board footer

Работает на PunBB
© Copyright 2002–2008 Rickard Andersson