Write a SQL query to get the nth highest salary from the Employee table.
+----+--------+
| Id | Salary |
+----+--------+
| 1 | 100 |
| 2 | 200 |
| 3 | 300 |
+----+--------+
For example, given the above Employee table, the nth highest salary where n = 2 is 200. If there is no nth highest salary, then the query should return null.
my answer
CREATE FUNCTION getNthHighestSalary(N INT) RETURNS INT
BEGIN
RETURN (
# Write your MySQL query statement below.
SELECT Salary FROM Employee ORDER BY Salary DESC LIMIT N-1, 1
);
END
error:
Runtime Error Message: Line 6: SyntaxError: near '-1, 1 ); END'
Last executed input: {"headers": {"Employee": ["Id", "Salary"]}, "argument": 1, "rows": {"Employee": [[1, 100]]}}
DELIMITER $
CREATE FUNCTION salarynth(n1 INT)
RETURNS INT
DETERMINISTIC
BEGIN
DECLARE myvar INT;
SELECT
SUBSTRING_INDEX(SUBSTRING_INDEX(CONCAT(group_concat(salary order by id),','), ',', n1),',',-1) INTO myvar FROM t;
RETURN myvar;
END$
DELIMITER ;
SELECT `salarynth`('3');
300
Related
So I have 2 tables named Employee(employeeID, salary) and Tax(employeeID, tax, revisedSalary), my aim is to calculate the tax and revised salary for all of the employees by extracting the values of the Salary column in the Employee Table, perform the calculations and store the results in the Tax table all this using stored procedures
Here is what I've tried to accomplish that, but without success so far, I'm getting 'Results consisted in more than one row' error:
delimiter //
create procedure calcTax()
begin
declare tax, salary, revisedSalary double default 0.0;
declare i int;
select Salary from Employee into salary;
while i <= salary do
if salary >= 0.0 and salary<= 10000.0
then
set tax = salary * 10/100;
set revisedSalary = salary - tax;
end if;
insert into Tax (tax, revisedSalary) values(tax, revisedSalary);
set i = i + 1;
end while;
end //
delimiter ;
Aside from the fact that you cannot store a result set in a variable your question doesn't make a lot of sense since you are attempting to calculate tax and salary per employee and you are inserting rows to tax without reference to employee. Also a while loop is unnecessary, the same can be achieved with a simple insert select
DROP TABLE IF EXISTS T,tax;
CREATE TABLE T
(employeeid int, salary int);
create table tax
(employeeid int, tax int , revisedsalary int);
insert into t values
(1,0),(2,5000),(3,7000),(4,15000);
insert into tax
select employeeid,
salary * .10,
salary - (salary * .10)
from t
where salary > 0 and salary <= 10000;
select * from tax;
+------------+------+---------------+
| employeeid | tax | revisedsalary |
+------------+------+---------------+
| 2 | 500 | 5000 |
| 3 | 700 | 7000 |
+------------+------+---------------+
2 rows in set (0.001 sec)
If you must us an sp
delimiter $$
create procedure p()
begin
insert into tax
select employeeid,
salary * .10,
salary - (salary * .10)
from t
where salary > 0 and salary <= 10000;
select * from tax;
end $$
delimiter ;
call p();
I have a table like this:
+----+--------+
| Id | Salary |
+----+--------+
| 1 | 100 |
| 2 | 200 |
| 3 | 300 |
+----+--------+
I am writing a function with mySQL to get the n th largest value in Salary.
Here is the function:
CREATE FUNCTION getNthHighestSalary(N INT) RETURNS INT
BEGIN
RETURN (
# Write your MySQL query statement below.
select DISTINCT Salary
FROM Employee
ORDER BY Salary DESC
LIMIT 1 offset (N - 1)
#FETCH NEXT 1 ROWS ONLY
);
END
But I got the an error near (N-1).
if I change (N-1) to 1 :
CREATE FUNCTION getNthHighestSalary(N INT) RETURNS INT
BEGIN
RETURN (
# Write your MySQL query statement below.
select DISTINCT Salary
FROM Employee
ORDER BY Salary DESC
LIMIT 1 offset 1
#FETCH NEXT 1 ROWS ONLY
);
END
It runs correctly.
So the question is how to reference input in SQL function? It seems it can be directly called as an argument as we do in other languages.
LIMIT argument cannot be a variable. Use prepared statement - in it the LIMIT parameter may be taken from a variable. But dynamic SQL is not allowed in the function - use stored procedure:
CREATE PROCEDURE getNthHighestSalary(N INT)
BEGIN
SET #sql := 'SELECT DISTINCT Salary
INTO #output
FROM Employee
ORDER BY Salary DESC
LIMIT 1 OFFSET ?';
PREPARE stmt FROM #sql;
SET #output := N-1;
EXECUTE stmt USING #output;
DROP PREPARE stmt;
SELECT #output;
END
fiddle
It seems I need to declare and set a variable before reference it in SQL query:
CREATE FUNCTION getNthHighestSalary(N INT) RETURNS INT
BEGIN
DECLARE M INT;
SET M=N-1;
RETURN (
# Write your MySQL query statement below.
select DISTINCT Salary
FROM Employee
ORDER BY Salary DESC
LIMIT 1 OFFSET M
#FETCH NEXT 1 ROWS ONLY
);
END
I am trying to create a POSTGRESQL function which would first INSERT some data in a table using WHILE LOOP and then SELECT the results of this table.
This is an sql example:
CREATE OR REPLACE FUNCTION get_levels_test (maxlevel int) RETURNS SETOF list_of_levels AS $$
DECLARE
level int = 1;
BEGIN
TRUNCATE list_of_levels;
WHILE (level <= maxlevel) LOOP
INSERT INTO list_of_levels
SELECT level;
level = level + 1;
END LOOP;
select * from list_of_levels;
END;
$$ LANGUAGE PLPGSQL VOLATILE;
Then i try to call this function with: select get_levels_test (3), which shows me this error:
ERROR: query has no destination for result data
Hint: If you want to discard the results of a SELECT, use PERFORM instead.
Where: PL/pgSQL function "get_levels_test" line 12 at SQL statement
The list_of_levels table contains just an int column.
In case this is needed, I am using PostgreSQL 8.2.15 (Greenplum Database 4.3.3.1 build 1).
You need to use "return next" which can be used with a composite type or with a table. Please use this feature with caution as you can have performance issues with using this. Do not use this to join the results to another table. Do not return large datasets with this. Only use it for very small results such as a short report.
You also need to add exception handling into your function. I added this to my example function below.
Example table:
create table employees
(id int not null,
manager_id int null,
employee_title text not null)
distributed by (id);
Example data:
insert into employees values
(1, null, 'President'),
(2, 1, 'Vice-President'),
(3, 2, 'Manager'),
(4, 3, 'Engineer'),
(5, null, 'CMO'),
(6, 5, 'Director'),
(7, 6, 'Assistant'),
(8, 7, 'Developer');
Function:
create or replace function get_employees(p_id int) returns setof employees as
$$
declare
v_function_name text := 'get_employees';
v_location int;
v_rec record;
v_rec2 employees;
v_id employees.id%type;
begin
v_location := 1000;
create temporary table t1
(id integer) on commit drop distributed by (id);
v_location := 2000;
for v_rec in (select id from employees where id = p_id and manager_id is null order by id) loop
v_id := v_rec.id;
insert into t1 values (v_id);
while v_id is not null loop
select id into v_id from employees where manager_id = v_id;
if v_id is not null then
insert into t1 values (v_id);
end if;
end loop;
end loop;
v_location := 3000;
for v_rec2 in (select * from employees e join t1 on e.id = t1.id order by e.id) loop
return next v_rec2;
end loop;
exception
when others then
raise exception '(%:%:%)', v_function_name, v_location, sqlerrm;
end;
$$
language plpgsql;
And using the function:
select * From get_employees(1);
id | manager_id | employee_title
----+------------+----------------
1 | | President
2 | 1 | Vice-President
3 | 2 | Manager
4 | 3 | Engineer
(4 rows)
select * From get_employees(5);
id | manager_id | employee_title
----+------------+----------------
5 | | CMO
6 | 5 | Director
7 | 6 | Assistant
8 | 7 | Developer
(4 rows)
I'm trying to create a mysql function, but i keep getting following error. What is the problem with my query?
You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'BEGIN INSERT INTO order (carID, clientID) Select car.id, client.id FROM' at line 2
My query:
DELIMITER //
CREATE FUNCTION orderCreate(LicenseNumber varchar(30), Phonenumber varchar(20))
BEGIN
INSERT INTO `order` (carID, clientID) Select car.id, client.id FROM car, client, owns WHERE car.licensenumber = LicenseNumber AND client.phonenumber = Phonenumber AND car.id = owns.carID AND owns.clientID = client.id;
RETURN mysql_insert_id();
END //
DELIMITER ;
FUNTION definition signature must have a RETURNS clause.
Your code did not use it.
And you can't use mysql_insert_id() within MySQL but PHP.
You have to use LAST_INSERT_ID().
Function:
delimiter //
drop function if exists orderCreate //
CREATE FUNCTION orderCreate( _LicenseNumber varchar(30), _Phonenumber varchar(20) )
RETURNS INTEGER
BEGIN
INSERT
INTO `order` ( carID, clientID )
SELECT car.id, client.id
FROM car, client, owns
WHERE car.licensenumber = _LicenseNumber
AND client.phonenumber = _Phonenumber
AND car.id = owns.carID
AND owns.clientID = client.id;
RETURN LAST_INSERT_ID();
END;
//
delimiter ;
And it would be a better practice to use different function/procedural parameter names over column names. Because unless used table name qualifiers with column names, there would arise an ambiguity in recognizing them and priority may be given to parameter names over column names.
select phonenumber from client;
Above statement may result all rows with input value PhoneNumber but not what you expected.
Example:
mysql> create procedure sp_so_q23838311( in deptno int )
-> select deptno from department
-> union all
-> select department.deptno from department;
Query OK, 0 rows affected (0.00 sec)
mysql> select deptno from department;
+--------+
| deptno |
+--------+
| 10 |
| 20 |
| 30 |
| 40 |
+--------+
4 rows in set (0.00 sec)
mysql> call sp_so_q23838311( 20 );
+--------+
| deptno |
+--------+
| 20 |
| 20 |
| 20 |
| 20 |
| 10 |
| 20 |
| 30 |
| 40 |
+--------+
8 rows in set (0.15 sec)
Documentation on FUNCTION:
CREATE FUNCTION Syntax for User-defined Functions
CREATE [AGGREGATE] FUNCTION function_name RETURNS {STRING|INTEGER|REAL|DECIMAL}
SONAME shared_library_name
I have a MyISAM table comprising over 2 million records, on which there is a FULLTEXT index over multiple columns.
Given a search term, I would like to know how many times it occurs within the indexed fields of each record.
For example, when searching for 'test' within the following table (in which there is a FULLTEXT index over both the FREETEXT and Third_Col columns):
+----+--------------------------------------------+---------------------------+
| ID | FREETEXT | Third_Col |
+----+--------------------------------------------+---------------------------+
| 1 | This is first test string in test example. | This is first test Values |
| 2 | This is second test. | This is sec col |
+----+--------------------------------------------+---------------------------+
I expect results like:
+----+-------+
| ID | count |
+----+-------+
| 1 | 3 |
| 2 | 1 |
+----+-------+
I know that in the FULLTEXT index MySQL uses dtf (the number of times the term appears in the document); how can one obtain this?
Create a user defined function like this
DELIMITER $$
CREATE FUNCTION `getCount`(myStr VARCHAR(1000), myword VARCHAR(100))
RETURNS INT
BEGIN
DECLARE cnt INT DEFAULT 0;
DECLARE result INT DEFAULT 1;
WHILE (result > 0) DO
SET result = INSTR(myStr, myword);
IF(result > 0) THEN
SET cnt = cnt + 1;
SET myStr = SUBSTRING(myStr, result + LENGTH(myword));
END IF;
END WHILE;
RETURN cnt;
END$$
DELIMITER ;
Then you can use this in your query as follows
select id, getCount(concat(FREETEXT, Third_col), 'test') from yourtable
Hope it helps