Currently I have this statement
IF(0.5 < SELECT (FLOOR(10*RAND()*pResourcium) AS TestVar FROM siegeverse.rooms rm) AS T))
THEN SELECT 'TEST'
Any idea why it is failing? Trying to get it to output test for each row if the selected element is greater than 0.5
Thanks!
SELECT statement in such scalar comparison contexts should return only one row. In your case, it might be returning multiple rows and so is failing. The following rewritten query is close to what you are interested in:
IF EXISTS (SELECT *
FROM
(SELECT
CASE
WHEN (FLOOR(10*RAND()*pResourcium) >= 0.5 THEN 'TEST'
ELSE NULL
END AS TestVar
FROM
siegeverse.rooms rm
) AS A
WHERE A.TestVar IS NOT NULL)
THEN
<run the stored procedure>
Related
I am trying create a dynamic dashboard in grafana 7.4.x with variables that can be selected. This works with one exception. In case there is no value selected, the value is empty and will result in a MySQL (5.7.32) error.
$value = 1,2,3
SELECT *
FROM TEST
WHERE ID IN ( ${test:csv} )
empty value results in :
$value = ''
SELECT *
FROM TEST
WHERE ID IN ( )
How can this query be rewriten in order to not result in an error but simply ignore this one where statement (as there are many ANDs)
You could use FIND_IN_SET in place of IN, as that function will take an empty string:
SELECT *
FROM TEST
WHERE FIND_IN_SET(ID, '$value')
You can try:
where id in (coalesce($value, 0))
but im not sure this will work with grafana query builder - but worth a try
Please, I do not understand why it is not working:
SET #key = (SELECT customer.key_stamp FROM customer WHERE customer.key_stamp = "0000");
CASE WHEN (#key > 0) THEN
INSERT INTO transaction
(transaction.to, transaction.key, transaction.type, transaction.cost_bitcoin, transaction.quantity)
VALUES ("0000", "f5rwsd", 2, 0.0075,
(500000 +
(
(SELECT bonus.amount
FROM bonus
WHERE 500000 BETWEEN bonus.min_quantity AND bonus.max_quantity
) / 500000
) * 100))
END;
I tried the CASE STATEMENT, but it still does not work, and i can't understand the issue.
Please help.
CASE is not a valid MySQL statement. (It's not a valid statement outside the context of a MySQL stored program.)
"Why it is not work"... is because it's not valid SQL.
A CASE expression can be used in a SQL statement where an expression is allowed. (In SQL, an expression returns a value of a particular datatype.)
As an example of using a CASE expression in a SQL statement, something like this:
SELECT CASE WHEN #key > 0 THEN 'somevalue' ELSE 'othervalue' END AS foo
in fact now i use just an sql functions, and it work now, all work, switch case mysql, if else statement mysql, and loops too, like while do, or LOOP ITERATE, all work, just need use it in sql functions, or sql procedure.
How can I test an IF statement in MySQL ?
I need to know, what happens when a query is into a IF statement and it returns nothing (0 row selected) ?
In other word, what a SELECT query returns when the no row is selected? Will it return NULL? If yes, so will this throw an error? IF ( NULL ) THEN ...? Or in this case just the statement of that IF won't execute?
In reality, I have a code like this:
IF ( SELECT banned FROM users WHERE id=new.user_id ) THEN
// do stuff
Note: banned column contains either 0 or 1.
All I want to know, is my code safe when that query doesn't return any row? I mean will it throw an error or nothing happens (just that IF statement doesn't execute) ?
Noted that I wanted to test it myselft, but I don't know how can I test a IF statement in MySQL. For example, I wanted to test it by this code:
BEGIN
IF ( SELECT banned FROM users WHERE id=new.user_id ) THEN
SELECT 'test';
ENDIF;
END
But code above doesn't even run. That's why I've asked this question.
An IF statement can be tested in the context of a MySQL stored program (a procedure, function or trigger.) MySQL doesn't support anonymous blocks.
To test an IF statement, you can create a procedure
DELIMITER $$
CREATE PROCEDURE foo
BEGIN
IF ( some_condition ) THEN
SELECT 'evaluation of some_condition returned TRUE' AS msg;
ELSE
SELECT 'evaluation of some_condition did NOT return TRUE' AS msg;
END IF;
END$$
DELIMITER ;
CALL foo;
I need to know, what happens when a query is into a IF statement and it returns nothing (0 row selected) ?
What you're actually asking about here is a scalar subquery.
Scalar subqueries return exactly one column and exactly one or zero rows. Returning NULL and matching zero rows are equivalent, and neither will throw an error. In both cases, the subquery's return "value" is NULL.
You will, however, throw an error if you manage to write a scalar subquery that returns more than one row (such as when you forget WHERE in the subquery. But zero rows is perfecty valid.
IF tests for truthiness, and anything that IS TRUE ... which technically means any expression that both IS NOT FALSE and IS NOT NULL -- satisfies the IF. If the return value is FALSE (0) or NULL then the ELSE branch will be followed, if present.
I highlighted keyword phrases like IS NOT FALSE, above, to emphasize the point that these are logical operators in SQL.
Try queries like SELECT 0 IS FALSE (returns 1, because it is) or SELECT NULL IS NOT TRUE (returns 1, because it isn't) or SELECT NULL IS NOT FALSE (also returns 1, because it isn't) SELECT NULL IS FALSE (returns 0, because it isn't) to see what I mean.
Let's say I have something as basic as
SELECT IF( (1 + 2) >=0, (1 + 2), 0)
FROM DUAL
which will obviously return 3.
Is there a way to NOT repeat the query I want to return (here 1 + 2)?
To put in context, I want to return the number of tasks remaining to do for the current month (at least 4 must be done), but if more than 4 are already done, there is no need to do more so I want to return 0.
What I have done is
IF((4 - IFNULL((LONG QUERY RETURNING THE NUMBER OF TASKS DONE THIS MONTH FOR A PARTICULAR USER ),0)) >= 0,
(4 - IFNULL((LONG QUERY RETURNING THE NUMBER OF TASKS DONE THIS MONTH FOR A PARTICULAR USER ),
0)
But is there a way to not repeat the query since it is long and I don't want the server to execute the same query twice?
Depending your request, you might want to use user-defined variables:
SELECT 1+2 INTO #tmp;
SELECT IF( #tmp >=0, #tmp, 0)
Or if you like one liners
SELECT IF( (#tmp := (1+2)) >=0, #tmp, 0)
-- ^ ^
-- don't forget those parenthesis !
EDIT: This works for "table select" statements too:
CREATE TABLE tbl AS SELECT 1 as a UNION SELECT 2;
SELECT SUM(a) FROM tbl INTO #tmp;
SELECT IF ( #tmp > 0, #tmp, 0);
If you look at http://sqlfiddle.com/#!2/37c33/1 for the execution plan of the above queries, you will see the second SELECT don't use the table.
BTW, please note that with your actual example, this could have been written:
SELECT MAX( (1+2), 0 )
-- ^^^^^ here your expression
... but I think this is not a property of your real query?
You can do this:
SELECT IF( (#a:=(1 + 2)) >=0, #a, 0);
One statement solution
A way to solve this problem in MySQL is to save the output of the heavy query and reuse multiple times. Take a look here:
SELECT CASE
WHEN #Value - 4 > 0
THEN #Value ELSE 0
END
FROM (SELECT #Value := (SELECT 1)) Query
where «SELECT 1» should be replaced by your query.
OT
Another way to perform your query would require the support of CTE (Common Table Expression).
For what I know this feature is missing in MySQL (How to transform a MSSQL CTE query to MySQL?)
Just to give you a taste of its expressiveness in MSSQL, where CTE is available, you could write something like that:
with Query (value)
as
(
select 1
)
select
case
when (select value from Query) - 4 > 0
then (select value from Query)
else
0
end
Indeed CTE are more powerful especially when dealing with recursive relations.
I need to query data from a second table, but only if a rare set of conditions in the primary table is met:
SELECT ..., IF(a AND b AND c AND (SELECT 1 FROM tableb ...)) FROM tablea ...
a, b, and c conditions are almost always false, so my thinking is the subquery will never execute for most rows in the result set and thus be way faster than a join. But that would only true if the IF() statement short circuits.
Does it?
Thanks for any help you guys can provide.
The answer is YES.
The IF(cond,expr_true,expr_false) within a mysql query is short-circuited.
Here a test, using #variables to prove the fact:
SET #var:=5;
SELECT IF(1 = 0, (#var:=#var + 1), #var ); -- using ':=' operator to modify 'true' expr #var
SELECT IF(1 = 1, #var, (#var:=#var + 1) ); -- using ':=' operator to modify 'false' expr #var
SELECT #var;
The result is '5' from all three SELECT queries.
Had the IF() function NOT short circuited, the result would be a '5' from SELECT #1, and '6' from SELECT #2, and a '7' from the last "select #var".
This is because the 'true' expression is NEVER executed, in select #1 and nor is the false expression executed for select #2.
Note the ':=' operator is used to modify an #var, within an SQL query (select,from, and where clauses). You can get some really fancy/complex SQL from this. I've used #vars to apply 'procedural' logic within a SQL query.
-- J Jorgenson --
With J. Jorgenson's help I came up with my own test case. His example does not try to short circuit in the condition evaluation, but using his idea I came up with my own test and verified that MySQL does indeed short-circuit the IF() condition check.
SET #var:=5;
SELECT IF(1 = 0 AND (#var:=10), 123, #var); #Expected output: 5
SELECT IF(1 = 1 AND (#var:=10), #var, 123); #Expected output: 10
On the second example, MySQL is properly short-circuiting: #var never gets set to 10.
Thanks for the help J. Jorgenson!
It depends.
IF doesn't short-circuit such that it can be used to avoid truncation warnings with GROUP_CONCAT, for example in:
set ##group_concat_max_len = 5;
select if(true or #var:=group_concat('warns if evaluated'), 'actual result', #var);
the result will be 'actual result' but you'll get a warning:
Warning (Code 1260): Row 1 was cut by GROUP_CONCAT()
which is the same warning you get with less trivial GROUP_CONCAT expressions, such as distinct keys, and without the IF at all.
Try it in the SQL analyzer. If you want to be on the safe side and not have to trust the database to work one way (and not to change that behavior ever in new versions), just make two queries and do the IF programmatically.