How do select data with IF ELSE statement in a MySQL query - mysql

I get data from MySQL with if statement as code below. but I get an error:
Error Code: 1241. Operand should contain 1 column(s).
so can someone can help me?
I can not put it into the procedure, because I am using spring + mybatis in the project and i will put this code into them.
SELECT IF((SELECT COUNT(*) FROM table1 WHERE someField = 'A') < 0,
(SELECT * FROM table2 WHERE someField = 'A'),
(SELECT * FROM table1 WHERE someField = 'A'))

From the comments: I wanna get data of 1 in 2 tables when table 1 don't have data I will get data from table 2.
That sounds like union all and not exists:
select * from table1 where someField = 'A'
union all
select * from table2 where not exists(select 1 from tabe1 where someField = 'A'
Note that, for this to work, both tables must contain exactly the same number of columns, whith aligned datatypes. You should really be enumerating the columns that you want to show in the resultset in both unioned queries, to avoid any possible ambiguity. If needed, you can cast columns or add litteral values to any or both of the resultset to align the resultsets (without seeing your actual data structures, I cannot tell how to do).

Related

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

update a table based on the outcome of a join in MySQL

I understand the syntax here:
UPDATE table
SET column1 = expression1,
column2 = expression2,
...
WHERE conditions;
and here:
UPDATE table1
SET column1 = (SELECT expression1
FROM table2
WHERE conditions)
WHERE conditions;
...but what if I want to update
UPDATE table1
SET column1 = expression
if we get a particular result on a join between table1 and table2
which has WHERE conditions?
I can't seem to figure it out, and I get syntax errors in all of my attempts. Any advice greatly appreciated.
The syntax in MySQL is:
UPDATE table1 JOIN
table2
ON conditions
SET table1.column1 = table2.expression1
WHERE conditions;
What I do is write it as a SELECT statement first.
SELECT t.id
, t.col AS old_val
, s.expr AS new_val
FROM target_table t
JOIN source_table s
ON s.somecol = t.somecol
AND s.othercol < 1
WHERE s.something_else = 'abc'
In this example, t.col is the column that I (eventually) want to assign a new value to. (Used in the SELECT statement here, this just displays the value currently stored in the column.)
The expression s.expr represents the expression that returns the value I want to assign to col. This could be as simple as a column reference, or can be a more complex expression.
The rest of the statement are the normal FROM, JOIN, ON and WHERE clauses we're familiar with.
Once I have a SELECT statement that is working, I can convert that into an UPDATE statement by
replacing SELECT ... FROM (at the beginning of the statement) with the keyword UPDATE
adding a SET clause before the WHERE clause.
For example, I would convert the SELECT statement above to something like this, to assign the value of s.expr to t.col:
UPDATE target_table t
JOIN source_table s
ON s.somecol = t.somecol
AND s.othercol < 1
SET t.col = s.expr
WHERE s.something_else = 'abc'
This the approach that works for me. Writing it as a SELECT first allows me to test, muck with the conditions and expressions, and review to verify which rows are going to be updated, what values are being replaced, and what values are going to be assigned to each row.

Case with result set in 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 ;

Mysql Query from Two table

Is it possible to join Two queries of mysql in a query ??
Like:
select * from a + select * from b
So that I can use them in a single php loop.
If they have the same number of columns and the datatypes are the same in each column, then you can use a UNION or UNION ALL:
select *
from a
UNION ALL
select *
from b
If you provide more details about the tables, data, etc, then there might be another way of returning this data.
A UNION will return only the DISTINCT values, while a UNION ALL selects all values.
If this is the route that you need to take, and you still need to identify which table the data came from, then you can always create a column to identify which table the data is from , similar to this:
select *, 'a' TableName
from a
UNION ALL
select *, 'b' TableName
from b
This allows you to distinguish what table the data came from.
I think it is easier creating sql "variables" like:
select varA, varb from TableA, tableB;
and you can just play with values in PHP accessing properties.
That way you can take conditions in the query like:
select varA, varb from TableA, tableB where varA.id = varB.foreingId bla bla...
;)

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