loop not working in mysql Stored procedure - mysql

read_loop:
LOOP
FETCH device_cur INTO device;
IF done1 THEN
LEAVE read_loop;
END IF;
set x = start;
repeat
SET tripcount = 0;
SET trip_previous = 0;
SELECT MAX(distinct(trip)) into tripcount from model_erv40 where date(log_time) = date(x) and device_id = device;
IF tripcount > 0 THEN
set y = 1;
repeat
SET cd = 0;
SELECT IFNULL(MAX(cumulative_distance), 0) into cd from model_erv40 where trip = y and date(log_time) = date(x) and device_id = device;
if cd > 0 then
if trip_previous = 0 then
set cdold = 0;
set cdcorrect = cd;
else
SELECT IFNULL(MAX(cumulative_distance), 0) into cdold from model_erv40 where trip = trip_previous and date(log_time) = date(x) and device_id = device;
set cdcorrect = cd - cdold;
end if;
SELECT users.id, users.verified INTO user_idv, verified FROM users INNER JOIN devices ON users.id = devices.user_id AND devices.id = device;
SELECT IFNULL(attribute_value, '') INTO group_code from user_attributes ua where ua.user_id = user_idv and ua.attribute_id = 1;
INSERT INTO trip_info(trip, user_id, device_id, IsVerified, groupcode, date, cumulative_distance) VALUES (y, user_idv, device, verified, IFNULL(group_code,''), x, ROUND(cdcorrect*0.0006214,2));
SET trip_previous = y;
end if;
set y = y + 1;
until y > tripcount
end repeat;
END IF;
set x = date_add(x, interval 1 day);
until x > enddate
end repeat;
END LOOP;
If i am removing the statement
SELECT g.groupcode INTO group_code FROM users u INNER JOIN
user_attributes ua ON u.id = ua.user_id AND ua.attribute_id = 1 AND
u.id = user_id INNER JOIN groupcode_master g ON ua.attribute_value =
g.groupcode;
then loop works fine and i am getting data for all the device but after adding that afore said statement i am getting data for only one device that means the loop is not continuing but i want to loop through all the device with the above statement. Please Help me ..Thanks in advance.

I have two notes:
...
INNER JOIN user_attributes ua ON u.id = ua.user_id AND ua.attribute_id = 1 AND u.id = user_id
...
'u.id = user_id' - if 'user_id' is a declared variable, it should be renamed because there is a field with the same name 'user_id'
ua.attribute_id = 1 - shouldn't it be in a WHERE clause?

Related

Stored procedure, I have an if else statement where I am executed until the if

DELIMITER //
CREATE PROCEDURE valor()
BEGIN
IF (select Garantia from repuestos_repuesto where Garantia = 'N' limit 1) = 'N' then
Select re.id ,ve.marca, ve.modelo, ve.año, re.Nombre_repuesto
from vehiculos_vehiculo as ve inner join repuestos_repuesto as re on re.Vehiculo_id = ve.id
where ve.marca='Chevrolet' and ve.modelo='Aveo Family' and ve.año = '2015' and re.Nombre_repuesto = 'Guardachoque' and re.Garantia = 'N'
Order By re.Precio Limit 1;
else
Select re.id ,ve.marca, ve.modelo, ve.año, re.Nombre_repuesto
from vehiculos_vehiculo as ve inner join repuestos_repuesto as re on re.Vehiculo_id = ve.id
where ve.marca='Chevrolet' and ve.modelo='Aveo Family' and ve.año = '2015' and re.Nombre_repuesto = 'Guardachoque' and re.Garantia = 'S'
Order By re.Precio Limit 1;
END IF;
END //
DELIMITER ;
call valor()
The idea is that in the first if it returns me the vehicles that do not have a guarantee and shows me the lowest price, and in the else those that do have a guarantee, but it does not show me any data when it goes to the else.
This spare part should print the stored procedure, in the else but it doesn't.

How to display all logic 'IF' in stored procedure mysql 5.7

I have a stored procedure with 1 parameter but linked to 3 tables, I want to display all of the table with one parameter with this query
CREATE DEFINER=`brambang`#`%` PROCEDURE `Read_discount_campaign`(IN Insert_ID INT(10)
)
proc:
BEGIN
DECLARE is_insert_id INT(10);
DECLARE param_1_message TEXT;
SET #is_insert_id = Insert_ID;
SELECT CONVERT( CONCAT('Maaf, ID discount_campaign tidak bisa \'0\'') USING UTF8) INTO param_1_message;
IF (Insert_ID = 0) THEN
SELECT param_1_message AS message;
LEAVE proc;
END IF;
IF (Insert_ID != 0) THEN
SELECT * FROM discount_campaigns where
id = #is_insert_id;
END IF;
IF (Insert_ID != 0) THEN
SELECT * FROM discount_campaign_advanced where
discount_campaign_id = #is_insert_id;
END IF;
IF (Insert_ID != 0) THEN
SELECT dcp.discount_campaign_id, CASE WHEN dcp.active = 0
THEN dcp.product_id ELSE pc.category_id END as discount_campaign_product
FROM discount_campaign_product dcp JOIN product_categories pc
ON dcp.product_id = pc.product_id
WHERE dcp.discount_campaign_id = Insert_ID;
END IF;
END
After I run this, the output was only from this query (last IF logic)
IF (Insert_ID != 0) THEN
SELECT dcp.discount_campaign_id, CASE WHEN dcp.active = 0
THEN dcp.product_id ELSE pc.category_id END as discount_campaign_product
FROM discount_campaign_product dcp JOIN product_categories pc
ON dcp.product_id = pc.product_id
WHERE dcp.discount_campaign_id = Insert_ID;
END IF;
Instead what I want is it displays all of the logic not only the last one, how to combine all of this logic so the output was from all of the logic, not only from the last logic, is it use cross join?

how save a selected record into a variable?

I'm in a problem with the following query ..
After inserting in the table rtoxvta record by record, I need before the end of the loop eliminate the record of the vta table prevously selected.
For that i declare a new variable and assign it the vta id .. but where do I do it?
DROP PROCEDURE IF EXISTS ROWPERROW;
DELIMITER ;;
CREATE PROCEDURE ROWPERROW()
BEGIN
DECLARE n INT DEFAULT 0;
DECLARE indexx INT DEFAULT 0;
#DECLARE aux INT DEFAULT 0;
SELECT COUNT(*) FROM rto INTO n;
SET n = n +1;
SET indexx=0;
WHILE indexx<n DO
INSERT INTO rtoxvta (fecharto, importerto, fechavta, importevta)
SELECT r.fecha, r.importe, v.fecha, v.importe
FROM vta v
left outer join rto r
ON r.id = indexx
WHERE v.fecha >= r.fecha
AND (
(v.importe = r.importe) OR
(v.importe + 2 = r.importe) OR
(v.importe + 1 = r.importe) OR
(v.importe - 1 = r.importe) OR
(v.importe - 2 = r.importe))
LIMIT 1;
SET indexx = indexx + 1;
#DELETE FROM vta WHERE id = aux;
END WHILE;
End;
;;
CALL ROWPERROW();
You'll have to do it as two steps. First get the ID of the record you're going to insert into a variable, then insert that record. Then you can delete the record.
WHILE indexx<n DO
SELECT v.id, r.id INTO #v_id, #r_id
FROM vta v
join rto r
ON r.id = indexx
WHERE v.fecha >= r.fecha
AND r.importe BETWEEN v.importe - 2 AND v.importe + 2
LIMIT 1;
INSERT INTO rtoxvta (fecharto, importerto, fechavta, importevta)
SELECT r.fecha, r.importe, v.fecha, v.importe
FROM vta v
CROSS JOIN rto r
WHERE v.id = #v_id AND r.id = #r_id;
SET indexx = indexx + 1;
DELETE FROM vta WHERE id = #v_id;
END WHILE;
Also, if you're using a column from rto in the WHERE clause, you should use INNER JOIN rather than LEFT OUTER JOIN. The WHERE condition will not match any rows that don't have a match in rto, so there's no point in using an outer join.

How to write if else statement for this?

I have the below code.
There is one which is one part which is "ISNULL(PO101_EXT_COST, 0)*MM01.MM021_RATE AS Amount, "
I will like to change to a if else statement.
When "MM01.MM021_RATE" = '1' then PO101_EXT_COST * MM021_FOREIGN_RATE
When "MM01.MM021_RATE" is not = '1' then PO101_EXT_COST * MM021_RATE
How can i change my code below?
SELECT
CASE
When MM01.MM021_RATE = 1
Then ISNULL(PO101_EXT_COST, 0)*MM01.MM021_FOREIGN_RATE
Else ISNULL(PO101_EXT_COST, 0)*MM01.MM021_RATE
END AS Amt END AS Amount,
ISNULL(IN100_INV_CODE,'') AS [Item Code],
ISNULL(IN006_DESC,'') AS Major,
ISNULL(IN007_DESC,'') AS Minor,
ISNULL(IN100_DESC,'') AS Item,
ISNULL(PO100_PO_REQ, 0) AS [PO #],
ISNULL(PO100_EVT_ID, 0) AS [Ev ID],
ISNULL(EV200_EVT_DESC, '') AS [Ev Desc],
ISNULL(PO101_EXT_COST, 0) AS OriginalAmt,
ISNULL(PO101_PHASE, '') AS Phase,
ISNULL(PO101_STATUS, '') AS Status,
ISNULL(EV870_ACCT_SECURITY,'') AS [ARCtl],
ISNULL(PO102_ACCOUNT,'') AS [GL Account],
MM01.MM021_EFFECTIVE_DATE,
MM01.MM021_RATE,
MM01.MM021_FOREIGN_RATE,
(PO101_ORG_CODE) AS ORG,
(PO101_CURRENCY) AS Currency, (PO100_APPROVAL) AS Approval
FROM PO101_ORD_DTL
LEFT OUTER JOIN PO100_ORDERS ON
PO100_ORG_CODE = PO101_ORG_CODE AND
PO100_PO_REQ = PO101_PO_REQ
LEFT JOIN PO102_DISTR ON
PO102_ORG_CODE = PO101_ORG_CODE AND
PO102_PO_REQ = PO101_PO_REQ AND
PO102_PO_REQ_SEQ = PO101_ORD_SEQ
LEFT OUTER JOIN EV200_EVENT_MASTER ON
PO100_ORG_CODE = EV200_ORG_CODE AND
PO100_EVT_ID = EV200_EVT_ID
LEFT OUTER JOIN MM021_CURRENCY_RATES MM01 ON
PO101_CURRENCY = MM01.MM021_CODE
INNER JOIN
(SELECT MM021_CODE, MAX(MM021_EFFECTIVE_DATE) AS EFFECTIVE_DATE
FROM MM021_CURRENCY_RATES
WHERE MM021_FOREIGN_RATE > 0 AND MM021_TO_CODE = '***'
GROUP BY MM021_CODE) MM02 ON
MM01.MM021_CODE = MM02.MM021_CODE AND
MM01.MM021_EFFECTIVE_DATE = MM02.EFFECTIVE_DATE
LEFT OUTER JOIN IN100_INV_MASTER ON
PO101_ITEM = IN100_INV_CODE AND
PO101_ORG_CODE = IN100_ORG_CODE
LEFT OUTER JOIN IN007_MINOR_GROUP ON
IN100_ORG_CODE = IN007_ORG_CODE AND
IN100_MINOR = IN007_MINOR AND
IN100_MAJOR = IN007_MAJOR
LEFT JOIN IN006_MAJOR_GROUP ON
IN006_ORG_CODE = IN007_ORG_CODE AND
IN006_MAJOR = IN007_MAJOR
LEFT JOIN EV870_ACCT_MASTER ON
PO101_BILLTO=EV870_ACCT_CODE AND
PO101_ORG_CODE=EV870_ORG_CODE
WHERE
(PO101_ORG_CODE = '40' ) AND
(EV200_EVT_DESC = 'Tyrexpo India 2016') AND
(ISNULL(PO100_APPROVAL,'') IN ('A9')) AND
(ISNULL(PO101_STATUS, '') IN ('O','C','H')) AND
(ISNULL(PO101_PHASE, '') IN ('1')) AND
(PO101_TAX_RES_TYPE <> '8APGST')
Thanks!
/*
DROP TABLE A;
DROP TABLE B;
CREATE TEMPORARY TABLE A (ID INT, rateid int,cost int);
CREATE TEMPORARY TABLE B(ID INT,rate int,foreignrate int);
TRUNCATE TABLE A;
INSERT INTO A VALUES(1,1,1),(2,1,null),(3,2,3),(4,2,null),(5,0,null),(6,7,null) ,(7,1,null) ,(8,0,null) ;
TRUNCATE TABLE B;
INSERT INTO B VALUES(1,10,20),(2,30,40);
*/
#SELECT A.* FROM A;
#SELECT B.* FROM B;
SELECT A.*,
case
when B.id = 1 then
case
when A.cost is not null and B.foreignrate is not null then A.cost * B.foreignrate
else 0
end
when B.id is not null then
case
when A.cost is not null and B.rate is not null then A.ID * B.rate
else 0
end
else 0
END AS AMT
FROM A
LEFT OUTER join B on B.ID = A.rateid

MySQL incrementing variable in stored procedure

So I have a routine that does (pseudo-code):
$rows = SELECT DISTINCT a, b FROM t1;
foreach($rows as $row) {
SET #i = 0;
UPDATE t1 SET c_index = #i := (#i+1)
WHERE a = $row[a] and b = $row[b] ORDER BY c DESC;
}
The point is to number a subset of rows by the way they are sorted. Works fine, but this is update runs thousands of times so is pretty slow. To speed it up I want to put it in a stored procedure.
BEGIN
DECLARE done INT DEFAULT 0;
DECLARE vA, vB, i INT;
DECLARE cur1 CURSOR FOR
SELECT DISTINCT a, b
FROM t1 WHERE ...;
DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = 1;
OPEN cur1;
WHILE done = 0 DO
FETCH cur1 INTO vA, vB;
IF done = 0 THEN
SET i=0;
UPDATE t1
SET c_index = i:= (i+1)
WHERE a = vA AND b = vB
ORDER BY c DESC;
END IF;
END WHILE;
CLOSE cur1;
END
However, when creating the above procedure MySQL says there is a syntax error at "i := ...". If I use a session variable for 'i' it works (#i). Using a session variable in a stored procedure is not very elegant. How can the above stored procedure be fixed without using a session variable for 'i'?
UPDATED: Since MySQL cursors are not updatable (read-only) there is no much sense of using one in your case. Almost everything you can possibly think of can be expressed just by pure UPDATE statement(s).
If (a, b, c) are unique you can do it this way
UPDATE table1 t JOIN
(
SELECT a, b, c,
(
SELECT 1 + COUNT(*)
FROM table1
WHERE a = t.a
AND b = t.b
AND c > t.c
) rnum
FROM table1 t
) s
ON t.a = s.a
AND t.b = s.b
AND t.c = s.c
SET t.c_index = s.rnum
Here is SQLFiddle demo
or if you happen to have some sort of id (e.g. auto_increment column) then
UPDATE table1 t JOIN
(
SELECT id,
(
SELECT 1 + COUNT(*)
FROM table1
WHERE a = t.a
AND b = t.b
AND c > t.c
) rnum
FROM table1 t
) s
ON t.id = s.id
SET t.c_index = s.rnum
Here is SQLFiddle demo