Case with result set in mysql - mysql

I want's to test following query in mysql
SELECT result.* FROM
(CASE WHEN (2 = 2)
THEN
(SELECT * FROM mytable WHERE myID =2814 )
END) result ;
but it is sending syntax error.
Any idea what's wrong with it ?

you can do it in a round about way like so
SET #query := NULL;
SELECT #query := t.qry
FROM
( SELECT
CASE WHEN 2 = 2
THEN "SELECT * FROM mytable WHERE myID =2814"
WHEN another_condition
THEN "another_select"
END as qry
) t ;
PREPARE query1 FROM #query;
EXECUTE query1;

This is too long for a comment.
Obviously, your query is equivalent to:
SELECT *
FROM mytable
WHERE myID = 2814;
This makes it a bit hard to figure out what you are asking.
Fundamentally, though case is an expression, and the from clause does not accept expressions. It accepts table names, view names, subqueries, and the like. Second, the case statement has a few other problems.
It returns a scalar scalar value. The subquery could return more than one row.
Returning more than one column is not allowed
All the clauses need to return the same thing
If you wanted to select from multiple tables -- and all of them have the same structure -- you can use a union all construct:
select t.*
from table2 t
where . . .
union all
select t.*
from table2 t
where . . .

I would prefer to use a different query each time (which at least will allow mysql some chance of using indexes properly).
However assuming there are several sub queries that you want as a source for data depending on the check then maybe something like this:-
SELECT result.*
FROM
(
SELECT * FROM mytable WHERE 2 = 2 AND myID = 2814
UNION
SELECT * FROM mytable2 WHERE 1 = 2 AND myID = 2814
UNION
SELECT * FROM mytable3 WHERE 3 = 2 AND myID = 2814
) result ;

Related

MySQL If variable equals then execute query

I have a requirement in MySQL 5.7 to only run a query if a condition is true.
For example, below we have a variable called x. If it equals 8, we're OK to run the query.
I'm trying to use an IF statement for this
Can anyone tell me what's going wrong?
Thanks
SET #x = (select count(*) from (select distinct tbl from db.tbl where dt = CURDATE())x);
IF #x = 8
BEGIN
SELECT * from db.tbl1
END
You don't need a procedure. Plain SQL will do:
SELECT * from db.tbl1
WHERE (select count(distinct col) from db.tbl where dt = CURDATE()) = 8
Note also the simplification using count(distinct ...)

WHERE x IN works with a single value, not with multiple on json

There's a hard to understand issue with querying on a json field in MySQL. The data column is of type json.
The following query works perfectly fine
SELECT * FROM `someTable` WHERE data->'$.someData' in ('A')
However the following one returns nothing.
SELECT * FROM `someTable` WHERE data->'$.someData' in ('A','B')
Funnily enough this also works:
SELECT * FROM `someTable` WHERE data->'$.someData'='A' OR data->'$.someData'='B'
I'm clueless as to why this happens. I originally thought that WHERE x IN executed in a json query format might be doing something like && but even if the values are ('A','A') it still returns nothing which essentially shows that more than one value in WHERE x IN wont work.
SAMPLE DATA (any would do really)
id | data (json)
1 | {"someData":"A"}
2 | {"someData":"B"}
Too long for a comment...
This seems to be related to an optimisation MySQL is performing when there is only one value in the IN expression (probably converting it to an a = b expression) and then it ignoring quotes. Strictly speaking,
SELECT *
FROM `someTable`
WHERE data->'$.someData' in ('A')
or
SELECT *
FROM `someTable`
WHERE data->'$.someData' = 'A'
should return no data because
SELECT data->'$.someData'
FROM someTable;
returns
"A"
"B"
which is not the same as A. You need to use JSON_UNQUOTE (or if you have MySQL 5.7.13 or later the ->> operator) to get the actual value of the someData key:
SELECT JSON_UNQUOTE(data->'$.someData') FROm someTable;
SELECT data->>'$.someData' FROm someTable;
which gives
A
B
which then works fine with an IN expression:
SELECT *
FROM `someTable`
WHERE JSON_UNQUOTE(data->'$.someData') in ('A','B')
-- or use WHERE data->>'$.someData' in ('A','B')
Output:
id data
1 {"someData":"A"}
2 {"someData":"B"}
Demo on dbfiddle
You could try using a join on a subquery instead of a IN clause
SELECT *
FROM `someTable` s
INNER JOIN (
select 'A' col
union
select 'B'
) t ON t.col = s.data->'$.someData

Case in mysql to execute another query based on condition

I have a problem, the concept is value from #count to perform if and execute the query. What should I do to fix it?
Here is my code:
SELECT
CASE WHEN ((SELECT COUNT(*) FROM tb_dana_user WHERE userid=1234 AND password=1234) = 0)
THEN (SELECT * FROM tb_dana_user)
ELSE (SELECT 'bar')
END
When I change SELECT * FROM tb_dana_user to SELECT 'its true', it's working properly. How to fix this case? Sorry for bad english .the concept is when its true then the query will execute SELECT * FROM tb_dana_user
The CASE expression evaluates to a value, i.e. it is used to evaluate to one of a set of results, based on some condition.
Example:
SELECT CASE
WHEN type = 1 THEN 'foo'
WHEN type = 2 THEN 'bar'
ELSE 'foo-bar'
END AS column_name
FROM sometable`
The CASE statement executes one of a set of statements returns one result, based on some condition.
then statement has a query(select * from tb_dana_user) which returns multiple rows.
In your case either you can limit the value returned for select * from tb_dana_user to one at the same time column also one.
SELECT
CASE WHEN ((SELECT COUNT(*) FROM tb_dana_user WHERE userid=1234 AND password=1234) = 0)
THEN (SELECT id FROM tb_dana_user limit 1)
ELSE (SELECT 'bar')
END

How do I run a CONCAT on query stored in a database

I know this is a bad example but I'm trying to simplify things so bear with me in the round-about way this code is written. Say I have queries stored in a database such as
queries table
id query
1 concat('SELECT * FROM table1 WHERE year = ', _year, 'order by name')
2 concat('SELECT * FROM table2 WHERE year = ', _year, 'order by name')
and I want to run the following routine
DECLARE _year;
SET _year= "2013";
SET #SQL = (SELECT query FROM queries WHERE id = 1);
PREPARE stmt FROM #SQL;
EXECUTE stmt;
this is what I currently have but it's not working. I'm trying to select a query from the database, pass a few variables into it and then run the query.
If it is possible to determine your query in advance, except for specific parameters, then you could consider using a UNION query with a discriminant. Then, use your queries table to select specific queries in the union and apply parameters to them. The queries themselves are defined in a view in the database.
SQL is intended in most DBMS to not be dynamic and the attempt to subvert this will almost certainly result in reduced performance and potential security problems.
CREATE VIEW UnionView
AS SELECT *, 1 as Type, Value1 AS Param FROM Table1
UNION ALL SELECT *, 2 as Type, Value2 AS Param FROM Table1
UNION ALL SELECT *, 3 as Type, Value3 AS Param FROM Table1;
SELECT * FROM UnionView WHERE Type = 2 AND Param = 2;
See SqlFiddle for an example to demonstrate the behaviour.

mysql and or query together

How can i run mysql and or query together instant of separate query.
e.g.:
And query:
select * form tablename where name='A' and password="A" and id='A';
Or query:
select * form tablename where name='A' or password="A" or id='A';
-These are 2 different query,can i make these query together?what is the syntax??
Use parentheses to group the conditions?
SELECT * FROM table WHERE (X and Y or Z) AND (P and Q or F)
Well, you can just union them but, since one is a subset of the other, it's not strictly necessary:
select * from tablename
where name = 'A' and password = 'A' and id = 'A'
union select * from tablename
where name = 'A' or password = 'A' or id = 'A'
That will give you exactly the same results as if you had just run the second query on its own. That will make sense once you realise that every single row from the first query has a name equal to 'A', so it will match the first part of the where clause in the second query.
If you want duplicate rows for those returned in both queries, just use union all instead of union.
If you were using 'A' as just a placeholder and its values are different in the two queries, then you have two approaches. Use a construct like:
... where (name = 'A' and password = 'B' and id = 'C')
or name = 'D' or password = 'E' or id = 'F'
or use the union solution I gave above, something like:
select * from tablename
where name = 'A' and password = 'B' and id = 'C'
union select * from tablename
where name = 'D' or password = 'E' or id = 'F'
(use union all when you know there is no possibility of duplicates between the two queries, - it will save the DBMS the trouble of removing non-existent duplicates - that's not the case with these queries).
The union may give better performance on a DBMS that can hive off the two selects more easily to separate query engines (something that would be more difficult with a single query with a complex where clause). Of course, as will all optimisations, measure, don't guess.
It is not clear what you expect as the result, but my guess is you want a UNION:
SELECT 1 `query`, `name`, `password`, `id`
FROM `tablename` WHERE `name`='A' and `password`='A' and `id`='A'
UNION
SELECT 2 `query`, `name`, `password`, `id`
FROM `tablename` WHERE `name`='A' or `password`='A' or `id`='A'
Note that the first column query in result is required to separate results from the two queries because union of (X and Y) and (X or Y) is always (X or Y).
Use () for such type of conditions
select * form tablename
where name='A' OR password="A" OR id='A' OR
(name='A' AND password="A" AND id='A')
If you want to check for same string as A here then you will get same o/p using following query
select * form tablename
where name='A' OR password="A" OR id='A'
Just combine the conditions with WHERE
SELECT * FROM tablename WHERE (name='A' AND password='A' AND id='A') OR name='A' OR password='A' OR id='A'
The parentheses ensure that the whole AND expressions "validates" only if ALL the containing conditions are true while the rest macthes the OR