Procedure Limit - mysql

I need help please! I tried searching for answers but didn't find anything.
I am using MYSQL6.
What I did is create 2 views and I want to limit these views to get a specific amount of results that is calculated through a function.
FUNCTION:
DELIMITER $$
CREATE FUNCTION `get_total_customers`() RETURNS int(11)
BEGIN
DECLARE TotalCustomers INT;
SELECT (count(customer_id)*0.2) INTO TotalCustomers FROM customer;
RETURN TotalCustomers;
END
VIEW1:
CREATE VIEW PreferredStatus AS
SELECT customer_id, SUM(amount) AS TotalAmount, get_total_customers() AS Total FROM payment
GROUP BY customer_id
ORDER BY TotalAmount DESC;
VIEW2:
CREATE VIEW RegularStatus AS
SELECT customer_id, SUM(amount) AS TotalAmount, get_total_customers() AS Total FROM payment
GROUP BY customer_id
ORDER BY TotalAmount ASC
LIMIT Total;
This is the procedure that would use the view.
> DELIMITER $$
CREATE PROCEDURE `CustomerStatus`(in custID int, out status varchar(200))
BEGIN
declare number1 int;
declare totalvar int;
declare limit2 int;
IF custID in (SELECT customer_id FROM PreferredStatus) THEN
set status = "preferred";
ELSEIF custID in (SELECT customer_id FROM RegularStatus) THEN
set status = "casual";
ELSE
set status = "regular";
End If;
END
HELP PLEASE!
-Thanks.

You can add LIMIT to the SELECT that creates the VIEW:
CREATE VIEW PreferredStatus AS
SELECT customer_id,
SUM(amount) AS TotalAmount,
get_total_customers() AS Total
FROM payment
GROUP BY customer_id
ORDER BY TotalAmount DESC
LIMIT 20;
sqlfiddle demo
A warning from the docs:
If a view definition includes a LIMIT clause, and you select from the
view using a statement that has its own LIMIT clause, it is undefined
which limit applies.

Related

Fetch all employees if not employee selected from UI else select specific employee data

I want to select all employees if no employee is selected else need data for selected employee.
I have written this query but it is throwing error.
DECLARE #emp_id INT
SET #emp_id=0 -- This will change based on the selected employee from UI
SELECT * FROM employees
WHERE employee_id in (CASE WHEN #emp_id=0 THEN (SELECT employee_id FROM employees) ELSE #emp_id END)
Sample Script for reproducing issue
CREATE TABLE employees (
employee_id INT ,
first_name VARCHAR (20) DEFAULT NULL,
last_name VARCHAR (25) NOT NULL
);
INSERT INTO employees values (1, '1_fname', '1_lname'),(2, '2_fname', '2_lname'),(3, '3_fname', '3_lname'),(4, '4_fname', '4_lname'),(5, '5_fname', '5_lname')
I want to this in single query.
Assuming that you're using prepared statements, you will need to provide the selected employee 2 times - as argument 1 and 2:
SELECT * FROM employees
WHERE CASE WHEN COALESCE(?,0) = 0 THEN TRUE ELSE id = ? END
For single query, we can INNER JOIN with same table to emulate whether employees should shown or not. Using this query will produce desired output.
select e.*
from employees e
inner join (
select employee_id,
case
when #emp_id = 0 then true -- will display all employees
when #emp_id = #emp_id then true -- only display selected employee
else false
end as is_shown
from employees
) filter on e.employee_id = filter.employee_id and filter.is_shown = 1;
Or using another approach
select employee_id, first_name, last_name
from (
select e.*,
case
when #emp_id = 0 then true
when #emp_id = employee_id then true
else false
end as is_shown
from employees e
) employees
where is_shown = 1;
Simple flow control inside stored procedure
delimiter $$
use `precise`$$
drop procedure if exists `GetEmployee`$$
create definer=`user`#`%` procedure `GetEmployee`(empID int)
begin
case when empID = 0 then
select *
from employees;
else
select *
from employees
where employee_id = empID;
end case
;
end$$
delimiter ;

ERROR 1172 (42000): Result consisted of more than one row on mysql stored procedure

I am getting ERROR 1172 (42000): Result consisted of more than one row on my stored procedure when I use CALL submitOrder( 10, 100, 1, #OrderId);
What went wrong in my code? The goal is to use the procedure to insert a new row into the orders table and a new row on the order details into order_items table.
DELIMITER //
CREATE PROCEDURE submitOrder(
IN customerId INT,
IN productId INT,
IN qty INT,
OUT orderId INT)
BEGIN
DECLARE orderId, storeId, staffId, qty, customerId, productId INT;
DECLARE listPrice DECIMAL(10,2);
DECLARE discount DECIMAL(4,2);
SELECT MAX(order_id)+1 FROM orders INTO #orderId;
SELECT s.store_id
FROM stocks AS s
INNER JOIN products AS p USING (product_id)
WHERE p.product_id = s.product_id
ORDER BY s.quantity DESC
LIMIT 1
INTO #storeId;
SELECT staffs.staff_id
FROM staffs
INNER JOIN stores
WHERE staffs.store_id = stores.store_id
LIMIT 1
INTO #staffID;
SET #qty = 1;
SELECT products.product_id
FROM products
WHERE products.product_id = productId;
SELECT products.list_price
FROM products
INTO #listPrice;
INSERT INTO orders VALUES (
#orderId, #customerId, 1, CURDATE(), ADDDATE(CURDATE(), INTERVAL 7 day), NULL, #storeId, #staffId);
INSERT INTO order_items
VALUES (#orderId, 1, #productId, #qty, #listPrice,0);
END//
DELIMITER ;
You forgot to put a WHERE clause and LIMIT 1 into the query that sets $listPrice. You also forgot to set #productId anywhere.
You can do both of these in the same query.
SELECT product_id, list_price
FROM products
WHERE product_id = productId
LIMIT 1
INTO #productId, #listPrice;
I'm not sure why you need the #product_id variable, since it will be the same as productId.

MySQL function with limit

I am trying to write a MySQL function with input variable like this
CREATE FUNCTION getNthHighestSalary(N INT) RETURNS INT
BEGIN
RETURN (
# Write your MySQL query statement below.
SELECT Salary FROM (SELECT * FROM Employee
ORDER BY Salary DESC LIMIT N-1, 1) AS tmp
);
END
And it reports error. However, the following code works
CREATE FUNCTION getNthHighestSalary(N INT) RETURNS INT
BEGIN
RETURN (
# Write your MySQL query statement below.
SELECT Salary FROM (SELECT * FROM Employee
ORDER BY Salary DESC LIMIT N, 1) AS tmp
);
END
Is there any way to achieve the goal that is to select the Nth highest salary with similar code? Thank you. (I am only allowed to change the content in the 'return' parentheses).
You can write something like this.
CREATE FUNCTION getNthHighestSalary(N INT) RETURNS INT
BEGIN
RETURN (
SELECT Salary FROM Employee e1
WHERE N-1 = (SELECT COUNT(DISTINCT salary) FROM Employee e2
WHERE e2.salary > e1.salary)
);
END

Find an average age range over a span of ages

I need to find the most occurrences in a 10yr age range that can be Age 2 to 22, 15 to 25, 10 to 20, etc. in a table with name & age
I've created the SQL that returns the average age:
SELECT age, count(age)
FROM member
GROUP BY age
ORDER BY COUNT(age) DESC
LIMIT 1
Thanks for your help!
Create another table ages to hold the age ranges you are interested in with a field for age_lower, age_upper and a display name age_range such as '2 to 22'
Join the tables with a WHERE clause that puts the age between the lower and upper ranges.
SELECT `age_range`, COUNT(`age`) AS age_count
FROM `member` INNER JOIN `ages`
ON age BETWEEN age_lower AND age_upper
GROUP BY age_range
ORDER BY COUNT(`age`) DESC, `age_range` ASC
SQL Fiddle
This might solve the problem. The only thing I added was a table to hold values 1..x where x is your bucket count. The #T can easily be replaced with your MySQL table name. The results are all possible sets the age falls in, for each age. Then count of how many equal sets.
--IGNORE BUILDING TEST DATA IN SQL SERVER
DECLARE #T TABLE(member INT,age INT)
DECLARE #X INT
SET #X=1
WHILE(#X<=100) BEGIN
INSERT INTO #T SELECT #X, CAST(RAND() * 100 AS INT)
SET #X=#X+1
END
DECLARE #MinAge INT=1
DECLARE #MaxAge INT=100
--YOUR SET TABLE. TO MAKE LIFE EASY YOU NEED A TABLE OF 1..X
DECLARE #SET TABLE (Value INT)
DECLARE #SET_COUNT INT =10
DECLARE #LOOP INT=1
WHILE(#LOOP<=#SET_COUNT) BEGIN
INSERT #SET SELECT #LOOP
SET #LOOP=#LOOP+1
END
SELECT
MinAge,
MaxAge,
SetCount=COUNT(CountFlag)
FROM
(
SELECT
MinAge=AgeMinusSetCount,
MaxAge=AgePlusSetCount,
CountFlag=1
FROM
(
SELECT DISTINCT
ThisAge,
AgeMinusSetCount=(AgeMinusSetCount-1) + Value,
AgePlusSetCount=CASE WHEN (AgeMinusSetCount-1) + Value + #SET_COUNT > #MaxAge THEN #MaxAge ELSE (AgeMinusSetCount-1) + Value + #SET_COUNT END
FROM
(
SELECT
ThisAge=age,
AgeMinusSetCount=CASE WHEN (age - #SET_COUNT) < #MinAge THEN #MinAge ELSE (age) - #SET_COUNT END
FROM
#T
)RANGES
LEFT OUTER JOIN (SELECT Value FROM #SET) AS FanLeft ON 1=1
)AS DETAIL
)AS Summary
GROUP BY
MinAge,
MaxAge
ORDER BY
COUNT(CountFlag) DESC

Returning procedure execution code in MySQL

I have a stored procedure
CREATE DEFINER=`root`#`localhost` PROCEDURE `GetNotExecutedOrders`(IN contractID INT(11))
BEGIN
SELECT idContract, idOrder, ProductID, Quantity, (SUM(`order`.Quantity))*(product.Price) as 'Total amount'
FROM typography.contract
JOIN typography.`order` ON contract.idContract=`order`.ContractID
JOIN typography.product ON `order`.ProductID=product.idProduct
WHERE idContract=contractID and ExecutionDate IS NULL
GROUP BY idOrder
ORDER BY idOrder;
END
I need to fix it so it returns an execution code <> 0 if there is no contract with such contract ID, and a list of contracts and an execution code = 0 if there is a contract with that contract ID.
Use an OUT parameter for the code. Then use a COUNT(*) query to set it.
CREATE DEFINER=`root`#`localhost` PROCEDURE `GetNotExecutedOrders`(IN contractID INT(11), OUT executionCode INT)
BEGIN
SELECT COUNT(*) > 0 INTO executionCode
FROM typography.contract
JOIN typography.`order` ON contract.idContract=`order`.ContractID
JOIN typography.product ON `order`.ProductID=product.idProduct
WHERE idContract=contractID and ExecutionDate IS NULL;
IF (executionCode)
SELECT idContract, idOrder, ProductID, Quantity, (SUM(`order`.Quantity))*(product.Price) as 'Total amount'
FROM typography.contract
JOIN typography.`order` ON contract.idContract=`order`.ContractID
JOIN typography.product ON `order`.ProductID=product.idProduct
WHERE idContract=contractID and ExecutionDate IS NULL
GROUP BY idOrder
ORDER BY idOrder;
END IF;
END