WHY can i not use if then with count() variable in MSQL - mysql

Srr can someone help me
i have next query for giving me the number of rows in a table
SET #UUIDTEST2 = 100;
SET #TESTNUMBER = 0;
SELECT #UUIDTEST2;
SELECT #UUIDTEST2 := count(*) from `swennenhome`.`tb_ElectrititeitLog` ;
SELECT #UUIDTEST2
This works BUT, when i add a if END IF Like this
SET #UUIDTEST2 = 100;
SET #TESTNUMBER = 0;
SET #TESTNUMBER = 0;
SELECT #UUIDTEST2;
SELECT #UUIDTEST2 := count(*) from `swennenhome`.`tb_ElectrititeitLog` ;
if (#UUIDTEST2 = 0) then
SET #TESTNUMBER = 5;
end if ;
SELECT #UUIDTEST2
i receive always a SQL syntax error.
I have be searching on google for 2 day's now and can't find the problem or a solution.

IF statement can be used in compound statement only.
Rather than IF function.
-- ...
SELECT #UUIDTEST2 := IF(count(*), count(*), 5)
from `swennenhome`.`tb_ElectrititeitLog`;
SELECT #UUIDTEST2;
But in your case, you may avoid using IF:
-- ...
SELECT #UUIDTEST2 := COALESCE(NULLIF(count(*), 0), 5)
from `swennenhome`.`tb_ElectrititeitLog`;
SELECT #UUIDTEST2;

Related

MySQL Variable Assignment via Procedure Not Working Correctly

In the code below, I'm trying go through the results of endDateTable row by row, comparing the current row's endDate to the previous row's endDate. If there has been any change since the previous, we increment #revisionNum. However, upon populating the new table, all of the #revisionNum entries are 0. What am I doing wrong?
NOTE: I'm using prepared statements in this manner since doing a straightforward SELECT into a variable gives a syntax error due to the LIMIT clause not allowing a variable in our version of MySQL.
BEGIN
DECLARE _currentEndDate DATETIME DEFAULT now();
DECLARE _priorEndDate DATETIME DEFAULT now();
SET #ResultsCount = (SELECT COUNT(*) FROM mainTable);
SET #j = 0;
WHILE #j < #ResultsCount DO
SET #revisionNum = 0;
/*CURRENT END DATE*/
SET #appResultQueryCurrent = CONCAT('
SELECT
end_date
INTO _currentEndDate
FROM endDateTable
LIMIT ', #j, ', 1'
);
PREPARE currentQueryStmt FROM #appResultQueryCurrent;
EXECUTE currentQueryStmt;
/*PREVIOUS END DATE*/
SET #appResultQueryPrior = CONCAT('
SELECT
end_date
INTO _priorAppEndDate
FROM endDateTable
LIMIT ', IF(#j = 0, 0, #j - 1), ', 1'
);
PREPARE priorQueryStmt FROM #appResultQueryPrior;
EXECUTE priorQueryStmt;
SET #revisionNum = IF(
#j = 0 OR (_currentEndDate = _priorEndDate),
#revisionNum,
IF(
_currentEndDate != _priorEndDate,
#revisionNum + 1,
#revisionNum
)
);
INSERT INTO finalTable (RevisionNum)
SELECT
#revisionNum AS RevisionNum
FROM endDateTable;
SET #j = #j +1;
END WHILE;
END $$
You don't need a loop, you can use INSERT INTO ... SELECT ..., incrementing the variable in the select query.
You also need an ORDER BY criteria to specify how to order the rows when comparing one row to the previous row.
INSERT INTO finalTable (RevisionNum, otherColumn)
SELECT revision, otherColumn
FROM (
SELECT IF(end_date = #prev_end_date, #revision, #revision := #revision + 1) AS revision,
#prev_end_date := end_date,
otherColumn
FROM endDateTable
CROSS JOIN (SELECT #prev_end_date := NULL, #revision := -1) AS vars
ORDER BY id) AS x
DEMO
The offset value in the LIMIT clause is tenuous without an ORDER BY.
Without an ORDER BY clause, MySQL is free to return results in any sequence.
There is no guarantee that LIMIT 41,1 will return the row before LIMIT 42,1, or that it won't return the exact same row as LIMIT 13,1 did.
(A table in a relational database represents an unordered set of tuples, there is no guaranteed "order" or rows in a table.)
But just adding ORDER BY to the queries isn't enough to fix the Rube-Goldberg-esque rigmarole.
In the code shown, it looks like each time through the loop, we're inserting a copy of endDateTable into finalTable. If that's 1,000 rows in endDateTable, we're going to get 1,000,000 rows (1,000 x 1,000) inserted into finalTable. Not at all clear why we need so many copies.
Given the code shown, it's not clear what the objective is. Looks like we are conditionally incrementing revisionNum, the end result of which is the highest revision num. Just guessing here.
If there is some kind of requirement to do this in a LOOP construct, within a procedure, I'd think we'd do a cursor loop. And we can use procedure variables vs user-defined variables.
Something along these lines:
BEGIN
DECLARE ld_current_end_date DATETIME;
DECLARE ld_prior_end_date DATETIME;
DECLARE li_done INT;
DECLARE li_revision_num INT;
DECLARE lcsr_end_date CURSOR FOR SELECT t.end_date FROM `endDateTable` t ORDER BY NULL;
DECLARE CONTINUE HANDLER FOR NOT FOUND SET li_done = TRUE;
SET li_done = FALSE;
SET li_revision_num = 0;
OPEN lcsr_end_date;
FETCH lcsr_end_date INTO ld_current_end_date;
SET ld_prior_end_date = ld_current_end_date;
WHILE NOT li_done DO
SET li_revision_num = li_revision_num + IF( ld_current_end_date <=> ld_prior_end_date ,0,1);
SET ld_prior_end_date := ld_current_end_date;
FETCH lcsr_end_date INTO ld_current_end_date;
END WHILE;
CLOSE lcsr_end_date;
INSERT INTO `finalTable` (revisionnum) VALUES (li_revision_num);
END $$
Note the "order by" clause on the SELECT, its not clear what the rows should be ordered on, so we're using a literal as a placeholder.
As the end result, we insert a single row into finalTable.
Again, it's not clear what the code in the question is supposed to achieve, but doing a cursor loop across ordered rows would be much more efficient than a bazillion dynamic SQL executions fetching individual rows.

MySQL: SET Variable in if exists condition

I am trying to set the variables while checking the if exists condition.
I have used := to set the variables, however, it for some reason it seems that when I try to set the variable in the if exists condition, it displays the result for the previous query.
Following is the code snippet from the stored procedure.
if exists (select #AccountVerified := AccountVerified, #IsActive := IsActive from tblUserLookUp where UserName = inUserName) then
begin
select "1: From if condition", #AccountVerified, #IsActive;
select #AccountVerified := AccountVerified, #IsActive := IsActive from tblUserLookUp where UserName = inUserName;
select "2: From select condition", #AccountVerified, #IsActive;
select #AccountVerified, #IsActive;
if #AccountVerified = 0 then
set outErrorCode = 3;
elseif #IsActive = 0 then
set outErrorCode = 4;
end if;
end;
else
set outErrorCode = 1;
end if;
I observed this by trying to print the values through the select statement after the if condition and after again running the select query on the table.
The
2: From select condition
seems to display the actual current results
However,
1: From if condition
seems to display the value from previous query.
Is there any concept of variable caching or it is that you cannot set variables in the if condition? I am also open to any other recommendation that you might have.
The only reason to do this is to save that select query on the same table as that of the if exists select query.
13.2.10.6 Subqueries with EXISTS or NOT EXISTS
...
Traditionally, an EXISTS subquery starts with SELECT *, but it
could begin with SELECT 5 or SELECT column1 or anything at all. MySQL
ignores the SELECT list in such a subquery, so it makes no difference.
...
An option:
...
SELECT
#AccountVerified := AccountVerified,
#IsActive := IsActive,
#Exists := TRUE
FROM tblUserLookUp,
(SELECT
#AccountVerified := NULL,
#IsActive := NULL,
#Exists := FALSE) `init`
WHERE UserName = inUserName;
IF (#Exists) THEN
...
ELSE
...
END IF;
...

Preventing duplicates while selecting into variable in MySQL

My function generates unique combinations from Items table and stores into list variable. In the end of generation, it returns list as a result and application processes every combination: saves into Combo table.
The Problem
It checks every time for duplicates from another tables called Combo which is getting filled in the second step of process (by application, not by function itself.)
But, It doesn't check for duplicates inside listvariable before inserting into it newly generated combinations.
So I'm getting result from function with duplicates inside the result itself. For example. 3423 appears here in the result 2 times:
3410;3463;3423;3489;3446;3445;3417;3436;3497;3454;3491;3420;3502;3496;3458;3493;3439;3499;3497;3487;3486;3504;3458;3501;3503;3441;3443;3453;3508;3474;3469;3497;3508;3433;3451;3449;3422;3453;3428;3475;3474;3458;3480;3422;3488;3432;3501;3414;3425;3444;3509;3502;3440;3422;3472;3501;3477;3483;3449;3480;3456;3463;3493;3476;3479;3425;3485;3464;3410;3434;3488;3504;3439;3423;3434;3486;3448;3456;3496;3413;3428;3482;3439;3437;3473;3420;3439;3470;3463;3494;3415;3442;3428;3500;3488;3478;3475;3417;3472;3463
How can I check list itself for duplicates before insertion?
Details
My function:
SELECT gen_n_uniq_perms_by_cat(1, 100, 1, 45, 1, 120, 20) as comb
which look like:
BEGIN
SET #result := "";
SET #counter := 0;
iterat :
LOOP
SELECT
gen_uniq_perm_by_cat(
permSize ,
user_id ,
catID ,
itemType ,
tsc_id ,
tries
) INTO #combo;
IF(ISNULL(#combo)) THEN
RETURN #result;
ELSE
SET #result := CONCAT_WS(';' ,#result ,#combo);
END
IF;
SET #counter := #counter + 1;
IF #counter > permCount THEN
RETURN #result;
END
IF;
END
LOOP
iterat;
END
and gen_uniq_perm_by_cat looks like:
BEGIN
iterat :
LOOP
SELECT
SUBSTRING_INDEX(
GROUP_CONCAT(`id` ORDER BY RAND() SEPARATOR '-') ,
'-' ,
permSize
) INTO #list
FROM
`Item`
LEFT JOIN `ItemCategory` ON `Item`.`id` = `ItemCategory`.`itemID`
WHERE
(`Item`.`user_id` = user_id)
AND(`ItemCategory`.`catID` = catID)
AND(`Item`.`type` = itemType);
SET #md5 := MD5(CONCAT_WS('-' , #list , tsc_id));
IF(
SELECT
count(*)
FROM
`Combo`
WHERE
`Combo`.`hash` = #md5
LIMIT 1
) = 0 THEN
RETURN #list;
END
IF;
SET tries := tries - 1;
IF tries = 0 THEN
RETURN NULL;
END
IF;
END
LOOP
iterat;
END
generates unique (never created in past) combinations by following arguments:
permSize = 1
permCount =100
user_id = 1
catID = 45
itemType = 1
tsc_id = 120
tries = 20
Use NOT LIKE for this purpose. In your case, replace corresponding condition lines with following:
IF(ISNULL(#combo)) THEN
RETURN #result;
END IF;
IF(#result NOT LIKE CONCAT('%' , #combo , '%')) THEN
SET #result := CONCAT_WS(';' ,#result ,#combo);
SET #counter := #counter + 1;
END IF;
IF #counter = permCount THEN
RETURN #result;
END IF;

How to change my sql to loop in MySql stored procedure in mysql?

When I write my sql in each statement,it works well.Now my sql is:
SELECT COUNT(*) INTO v_Point1Num from tbpoint where Point=1;
SELECT COUNT(*) INTO v_Point2Num from tbpoint where Point=2;
SELECT COUNT(*) INTO v_Point3Num from tbpoint where Point=3;
SELECT COUNT(*) INTO v_Point4Num from tbpoint where Point=4;
SELECT COUNT(*) INTO v_Point5Num from tbpoint where Point=5;
and it work well.
Now I try to change it to loop,but it is wrong,how to fix it?I wonder it is the reason that I do not use "#" like "#v".
--can not work.
CREATE `SP_Point`()
BEGIN
DECLARE v INT DEFAULT(0);
DECLARE pointlStr VARCHAR(800);
SET v = 1;
WHILE v <= 5 DO
SELECT COUNT(*) INTO
(case v
when 1 then concat('v_Point',v,'Num')
when 2 then concat('v_Point',v,'Num')
when 3 then concat('v_Point',v,'Num')
when 4 then concat('v_Point',v,'Num')
when 5 then concat('v_Point',v,'Num')
)
from tbpoint
where Point=v;
SET v = v + 1;
END WHILE;
END
I try to change it to the other way,but it is still wrong.
SET v = 1;
WHILE v <= 5 DO
set pointlStr=
'SELECT COUNT(*) INTO #v_Point'+#v+'Num from tbpoint
where Point='+#v;
prepare stmt from #pointlStr;
execute stmt;
SET v = v + 1;
END WHILE;
You are trying to create a new variables(v_Point1Num, v_Point2Num.... etc) at run time which is not possible into mysql. you must declare a variable before using it.
You can achieve the same output by running single query as well... rather then running multiple queries
SELECT Point, COUNT(*) from tbpoint
group by Point
having point > 0 and point <= 5;
Concat() function return the varchar/String not the variable name. declare only one variable "v_pointNum"... fetch the value into variable inside loop.... and in the same loop update the other table as well. –
CREATE `SP_Point`()
BEGIN
DECLARE v INT DEFAULT(0);
-- declare a variable to hold count value
DECLARE v_pointNum INT DEFAULT(0);
DECLARE serviceAttitudeLevelStr VARCHAR(800);
SET v = 1;
WHILE v <= 5 DO
SELECT COUNT(*) INTO v_pointNum from tbpoint where Point=v;
-- update another table
update <mytable> set <mycol> = v_pointNum where <condition>;
SET v = v + 1;
END WHILE;
END

Using an if statement outside a stored procedure

I am trying to execute this code
set #id = 0;
set #the_number = 0;
set #the_message = 0;
set #selected_message = 0;
SELECT id, dest_msisdn, text_message INTO #id, #the_number, #the_message FROM incoming_sms where service_id = 6015592000101762 AND job_status = 0 limit 1;
if(#the_message LIKE '%Bank%')then
select 'h';
end if;
but i keep getting an error on
if(#the_message LIKE '%Bank%')then
select 'h'' at line 1
Why is my if producing an error?.
You need to put your code inside of a strored procedure or function to use the IF statement https://stackoverflow.com/a/12954385/5308054. Here you can see a feature request to fix it https://bugs.mysql.com/bug.php?id=48777
It is possible to rewrite query without IF statements but I think this question is too to be answered in such way.